Racket Boggle Game - racket

I am working on a big boggle game in racket for a class. I am still trying to figure out racket so I am really struggling with this. I am supposed to print out a 5x5 board with random letters in it and then I need to print out a list of lists with the characters from the board for my instructor to use in his player. However when I call the instructors-player it is generating a new list of characters. Any thoughts on what I might be doing wrong?
Creating my lists:
(define alphabet (list "B " "C " "D " "F " "G " "H " "J " "K " "L " "M " "N" "P " "R " "S " "T " "V " "W " "X " "Y " "Z "))
(define vowel (list "A " "E " "I " "O " "U "))
(define (pick-item alphabet)(list-ref alphabet (random(length alphabet))));;select element randomly from alphabet list
(define (pick-vowel vowel)(list-ref vowel (random(length vowel)))) ;;select element randomly from vowel list
(define (make-row alphabet) (list (pick-item alphabet)(pick-vowel vowel)(pick-item alphabet)(pick-vowel vowel)(pick-item alphabet))) ;;make a list of vowels and consonants
(define (make-board) (list (make-row alphabet) (make-row alphabet) (make-row alphabet) (make-row alphabet) (make-row alphabet))) ;;make a list of 5 lists for board
(define (instructors-player gameGrid) (make-board) )
Drawing the board and calling the instructors-player
(define gameGrid(draw-board (make-board)))
(instructors-player gameGrid);;call for instructors input

Try this:
(define a-board (make-board)) ; make a board
(draw-board a-board) ; draw the board
(instructors-player a-board) ; give a-board to the instructor's player
Maybe the last line needs to be:
(draw-board (instructors-player a-board))

Related

how can I match on a datum?

I'd like to write a pattern that only matches on a single datum like 'a or 'hello but not anything else. I don't think the following works as it matches on everything (like (list 1 2 3))right?
(define (f x)
(match x (e (printf "hi~n"))))
Datums can be used as patterns. Here is an example:
#lang racket
(define (f x)
(match x
["hello" "x is hello"]
[_ "x is not hello"]))
(f "hello")
(f 42)
The result is:
"x is hello"
"x is not hello"
Also if you want to use a fixed symbol as a pattern use 'hello and not just hello. The first 'hello matches a single symbol but hello is a pattern variable and matches everything.

How do I format a single backslash in common lisp?

I'm currently trying to get an output of ... \hline in GNU Common lisp 2.49, but I can't get the format to work. This is what I've tried so far to get a single backslash:
(format nil "\ ") => " "
(format nil "\\ ") => "\\ "
(format nil "\\\ ") => "\\ "
I thought that the double backslash would make it work, why isn't the backslash escaping just the other backslash?
See for example:
CL-USER> (write "\\" :escape nil)
\
"\\"
Here above, the first backslash is your string, printed without escaping backslashes. The returned value is the string, printed by the REPL with the standard io syntax (http://clhs.lisp.se/Body/m_w_std_.htm), which escapes strings.
So, your string contains a single backslash, but is printed in such a way that it can be read back, hence the need to escape the backslash in the output string.
Note also that calling format with NIL and a single string returns the same string.
You can inspect your strings, for example by mapping each character to its name:
(loop
for input in '("\ "
"\\ "
"\\\ ")
collect (list :input input
:characters (map 'list #'char-name input)))
This gives:
((:INPUT " " :CHARACTERS ("Space"))
(:INPUT "\\ " :CHARACTERS ("REVERSE_SOLIDUS" "Space"))
(:INPUT "\\ " :CHARACTERS ("REVERSE_SOLIDUS" "Space")))
Or, simply use inspect:
CL-USER> (inspect "\\hline")
The object is a VECTOR of length 6.
0. #\\
1. #\h
2. #\l
3. #\i
4. #\n
5. #\e
Note the difference between creating a string and actually doing output to a stream:
CL-USER 69 > (format nil "\\ ")
"\\ " ; result
CL-USER 70 > (format t "\\ ")
\ ; output
NIL ; result
CL-USER 71 > (format *standard-output* "\\ ")
\ ; output
NIL ; result

lisp remove a the content of one list from another list

I have a list of string like this called F:
("hello word i'am walid" "goodbye madame") => this list contain two elements of string
and I have another list call S like this ("word" "madame") => this contain two words
now I want to remove the elements of the list S from each string of the list F and the output should be like this ("hello i'am walid" "goodbye")
i found already this function:
(defun remove-string (rem-string full-string &key from-end (test #'eql)
test-not (start1 0) end1 (start2 0) end2 key)
"returns full-string with rem-string removed"
(let ((subst-point (search rem-string full-string
:from-end from-end
:test test :test-not test-not
:start1 start1 :end1 end1
:start2 start2 :end2 end2 :key key)))
(if subst-point
(concatenate 'string
(subseq full-string 0 subst-point)
(subseq full-string (+ subst-point (length rem-string))))
full-string)))
example:
(remove-string "walid" "hello i'am walid") => the output "hello i'am"
but there is a problem
example:
(remove-string "wa" "hello i'am walid") => the output "hello i'am lid"
but the output should be like this "hello i'am walid" in another word i wont the remove the exact word from the string
please help me and thank's
You can use the cl-ppcre library for regular expressions. Its regex flavour understands the word boundary \b.
The replacement could work like this:
(cl-ppcre:regex-replace-all "\\bwa\\b" "ba wa walid" "")
=> "ba walid"
I guess that you want to collapse any whitespace around the removed word into one:
(cl-ppcre:regex-replace-all "\\s*\\bwa\\b\\s*" "ba wa walid" " ")
=> "ba walid"
See the documentation linked above.
UPDATE: You extended the question to punctuation. That's actually a tad more complicated, since you now have three kinds of characters: alphanumeric, punctuation, and whitespace.
I can't give a complete solution here, but the outline I envision is to create boundary definitions between all three of these kinds. You need positive/negative lookaheads/lookbehinds for that. Then you look at the replaced string, whether it starts or ends with punctuation and append or prepend the corresponding boundary to the effective expression.
For defining the boundaries in a readable manner, the parse tree syntax of cl-ppcre might prove useful.
The Common Lisp Cookbook provides this function:
(defun replace-all (string part replacement &key (test #'char=))
"Returns a new string in which all the occurences of the part
is replaced with replacement."
(with-output-to-string (out)
(loop with part-length = (length part)
for old-pos = 0 then (+ pos part-length)
for pos = (search part string
:start2 old-pos
:test test)
do (write-string string out
:start old-pos
:end (or pos (length string)))
when pos do (write-string replacement out)
while pos)))
Using that function:
(loop for raw-string in '("hello word i'am walid" "goodbye madame")
collect (reduce (lambda (source-string bad-word)
(replace-all source-string bad-word ""))
'("word" "madame")
:initial-value raw-string))

Mapping source code line number to "printed" page number

Sometimes I search in emacs for some variable then try to find which page should I look for in the printout of the file I have in hand.
Is it possible, given the printing parameters I use, to have emacs show a "virtual" page number that maps to the where the cursor is pointing at?
I am trying to play with the "mode line", given that each printed page has 72 lines, then page number = line_number/72+1.
This did not work though:
(setq-default mode-line-format
'("" mode-line-modified ""
mode-line-buffer-identification "-"
"[" mode-name "." mode-line-process "." minor-mode-alist "" "%n" "]"
line-number-mode "-" "L%l"
"-" "P" (+ 1 (/ %l 72))
column-number-mode "-" "C%c"
mode-line-misc-info ""
abbreviated-file-name
"%-"
)
)
Anny pointers?
You can force mode-line updates (force-mode-line-update) with something like the post-command-hook.
(setq-default mode-line-format '(
" "
(:eval (format "Line %s | Page %s"
(line-number-at-pos) (+ 1 (/ (line-number-at-pos) 72)) ))))

Create a list of pairs from a list

I'm new to Lisp and have no idea how to write this...
You give: ("Test" "TEST" "third" "the last")
You get: (("A" . "Test") ("B" . "TEST") ("C" . "third") ("D" . "the last"))
Function: (defun choices (&rest choices))
In C, I can just write a for for this, but Lisp can't +1 to string and loop doesn't have a counter, either... Could someone please give me a sample?
I would write something like this:
(defun choices (&rest choices)
(loop for i from 1 to 26
and item in choices
collect (cons (string (digit-char (+ 9 i) 36))
item)))
The above code has no error checking for more than 26 choices (and you
didn't specify how to handle them if it's not an error).
You could use CHAR-CODE and CODE-CHAR to "increment a character",
but the encoding they provide is not standardized (only some
properties of it are guaranteed). With DIGIT-CHAR in radix 36, we're
guaranteed to get the English alphabet (uppercase) for weights 10 to
35.
And of course, LOOP has a lot of things, including whatever counters you want.
You can concatenate two lists in the way you described by simply doing mapcar+cons:
(mapcar #'cons '("A" "B" "C" "D") '("Test" "TEST" "third" "the last"))
; => (("A" . "Test") ("B" . "TEST") ("C" . "third") ("D" . "the last"))
Since the second list is given, now the problem is only in generating the ABCD list. That can be achieved with loop and code-char:
(loop for i from 65 to 68 collect (string (code-char i)))
; => ("A" "B" "C" "D")
Combining those two into an answer and tailoring it to your specific problem should be easy now.