

jbetz34
Forum Replies Created
-
Hi Megan,
If all you want is to print these statements, you don’t necessarily need to cast the columns to symbols or save in a table. Try the following one-liner:
{x,” from “,y,” scored a goal in the “,z,”th minute”}./: flip(“***”;”;”) 0:`:goals.txt
By default this prints to the console, so I don’t see why you would need to include the “0N!” .
The reason you are getting a parse error on the “0N! each ” is because “0N!” is an infix function followed by a postfix iterator. You will have to wrap “0N! in parenthesis (see https://code.kx.com/q/basics/syntax/#prefix-infix-postfix). Also worth noting that “0N!/:” will work here as well. However, I think even this is unnecessary as “0N!” is unary and natively handles a list of strings.
-
Spoiler rnd:{[x;nd;m] string%[;s]((ceiling;floor;7h$)`up`dn`nr?m)@:x*s:10 xexp nd}?
Stealing your solution here, except
floor 0.5+
can be replaced with7h$
. It is slightly more efficient and will save about 10 characters, if that matters -
Very cool. A possible improvement might be to asynchronously push on a timer from the q server once connection has been established. That way you don’t have to refresh every time to see the snow fall. Can’t wait to try for myself.
-
Hi Paul,
Awesome brain teaser!
I was inspired by your scoring method to continue development beyond line 1.To begin, I used the same import and sanitize functions that you did:
wordz:system “curl http://wiki.puzzlers.org/pub/wordlists/unixdict.txt“; wordz:wordz where all (5=count each wordz;all each wordz in .Q.a);
However, instead of using a dictionary format to calculate letter scores, I used a table format. Table format would simplify the query/filtering process as we continue to guess possible words.
I started with a base table of all the wordz, separating each letter into a positional column in roman numerals (i.e I,II,III –> 1,2,3).
// create base word table w:([] word:wordz; I:wordz[;0]; II:wordz[;1]; III:wordz[;2]; IV:wordz[;3]; V:wordz[;4]); // note that all columns are string type q) w word I II III IV V --------------------- "aaron" a a r o n "ababa" a b a b a "aback" a b a c k "abase" a b a s e "abash" a b a s h
Next, to replicate the wordzScore using the table format , I created a generic probability function that would accept a table of words similar to the base table and a column to analyze. It returns a dictionary of letter probability within that positional column
// generic wordzScore function // x - words table // y - column to analyze prb:{{x%sum x} ?[x;();y;(count;`i)]}; q)prb[w;`I] a| 0.06868045 b| 0.08426073 c| 0.08330684 d| 0.05055644 e| 0.03561208
I applied that function to each column, summed across columns and applied back to the original table:
// apply probability func across columns s:?[t;();0b;n!{(@;x y;y)}[prb[t]] each n:`I`II`III`IV`V]; // sum across columns and apply to base table t:update score:(exec sum (I;II;III;IV;V) from s) from t; q) t word I II III IV V score ------------------------------- "sauce" s a u c e 0.6 "saute" s a u t e 0.6 "salle" s a l l e 0.5974563 "caine" c a i n e 0.5971383 "slate" s l a t e 0.5879173
Great! Now we are all caught up to where you left off, but in table format.
One of the most important aspects to wordle is understanding and properly responding to the clues that the game will give after each guess. There are 3 options for each letter:
- it is not in the word
- it is in the word, but not in correct position
- it is in the word and in the correct position
We can use these clues to limit our words table and recalculate the wordzScore at each step to make sure we take the best guess at each opportunity. I viewed this in 3 parts:
- Record guesses and clues from game
- Build filter clauses from these clues
- Use these filters to recalculate wordzScore
Starting with the easiest step, #3. Lets put the wordzScore calculation in a function that accepts a parse tree of ‘where’ clauses as an argument:
// where w exists globally and is base word table // where prb exists globally and is letter probability function topList:{[wc] t:?[`w;wc;0b;()]; s:?[t;();0b;n!{(@;x y;y)}[prb[t]] each n:`I`II`III`IV`V]; t:update score:(exec sum (I;II;III;IV;V) from s) from t; `score xdesc t }
Then, lets create a table where we can record our guesses, clues from the game and the resulting word filters from that guess (can you tell I love tables?). Simple enough:
guessTable:([]guess:();clues:();wc:())
Now comes the tricky part, how to we build a function to generate filters based on the clues. Here’s what I came up with. It is not the most elegant and can definitely be optimized, but it gets the job done.
// expecting string guess (g) // list of longs corresponding to clues (c) // 0 - not in word; // -1 - correct letter, wrong spot; // 1 - correct letter, correct spot; guess:{[g;c] // if letter is in wrong spot, filter out words where that letter is in that position column wc:{(not;(in;`I`II`III`IV`V@y;x y))}[g] each where c=-1; // if letter is in wrong spot, also filter for words where that letter is in the word column wc,:{(in/:;x y;`word)}[g] each where c=-1; // if letter is not in word, filter out words with that letter in the word column wc,:{(not;(in/:;x y;`word))}[g] each where c=0; // if letter is in the right spot, filter for words with that letter in that position column wc,:{(in;`I`II`III`IV`V@y;x y)}[g] each where c=1; // upsert the guess, clues and filters to the guessTable and display `guessTable upsert enlist (g;c;wc); :guessTable }
Tying it all together, lets try it out on a sample 5 letter word like “water”:
q)l qWordle.q q)1#topList() word I II III IV V score --------------------------- "sauce" s a u c e 0.6 // manually entering clues q)guess["sauce";0 1 0 0 -1] guess clues wc ----------------------------------------------------------------------------------------------------------------------------------- "sauce" 0 1 0 0 -1 (~:;(in;`V;"e")) (in/:;"e";`word) (~:;(in/:;"s";`word)) (~:;(in/:;"u";`word)) (~:;(in/:;"c";`word)) (in;`II;"a") q)1#topList raze guessTable`wc word I II III IV V score ----------------------------- "hater" h a t e r 2.62069 // manually entering clues q)guess["hater";0 1 1 1 1] guess clues wc ------------------------------------------------------------------------------------------------------------------------------------- "sauce" 0 1 0 0 -1 ((~:;(in;`V;"e"));(in/:;"e";`word);(~:;(in/:;"s";`word));(~:;(in/:;"u";`word));(~:;(in/:;"c";`word));(in;`II;"a")) "hater" 0 1 1 1 1 ((~:;(in/:;"h";`word));(in;`II;"a");(in;`III;"t");(in;`IV;"e");(in;`V;"r")) q)topList raze guessTable`wc topList raze guessTable`wc word I II III IV V score ------------------------------ "bater" b a t e r 4.111111 "dater" d a t e r 4.111111 "eater" e a t e r 4.111111 "later" l a t e r 4.111111 "mater" m a t e r 4.111111 "pater" p a t e r 4.111111 "rater" r a t e r 4.111111 "tater" t a t e r 4.111111 "water" w a t e r 4.111111
At this rate, I don’t think we will get it in 6 guesses. But who knew there were so many “*ater” words?
I am sure there are many improvements to be made here, but I have also spent too much time on this today.Thanks Paul, looking forward to more awesome content like this.
– James
-
-
q is built on k4, but shakti (k9) has many similar aspects to the k4 language and is better documented here: https://estradajke.github.io/k9-simples/k9/index.html
-
Thanks, sounds like I need an upgrade! I should have checked the release notes first, sorry