Draw text in Racket - racket

I need to draws a slide, showing only its title and shown part on a large background of a fixed size. Should I use the (text " " 25 "black") or just use the slide. Beside text function, is there other function can draw text?
(define SLIDE-1-LOS
(cons "Designing programs to solve problems"
(cons "Building good habits for developing large systems with a team"
(cons "CS: fundamental ideas, thinking" '()))))
(define SLIDE-2-LOS
(cons "Effectively using computers as tools"
(cons "Breaking down problems" '())))
(define SLIDE-3-LOS
(cons "Easy to start"
(cons "Informative feedback"
(cons "Functional programming is a useful paradigm" '()))))
(define-struct slide [title shown hidden])
(define SLIDE-1
(make-slide
"What is Fundies 1 About?"
'() SLIDE-1-LOS))
(define SLIDE-1-NEXT
(make-slide
"What is Fundies 1 About?"
(cons "Designing programs to solve problems" '())
(cons "Building good habits for developing large systems with a team"
(cons "CS: fundamental ideas, thinking" '()))))
(define SLIDE-1-NEXT-NEXT
(make-slide
"What is Fundies 1 About?"
(cons "Designing programs to solve problems"
(cons "Building good habits for developing large systems with a team" '()))
(cons "CS: fundamental ideas, thinking" '())))
(define SLIDE-1-DONE
(make-slide "What is Fundies 1 About?"
SLIDE-1-LOS '()))
(define bg(square 400 "solid" "white"))
(define (draw-slide s)
(place-image
overlay
;what should I put in between this
bg)

If you are a student studying HtDP:
You should follow the design recipe. In particular, what is the template for a function taking a slide?
Yes, text seems like a reasonable way of turning a string into an image.
place-image is one way of combining images, but it isn't the only one. What other functions are available for combining images?
You should not post homework solutions on stackoverflow.
If you are not a student:
You can use the Slideshow language/library in Racket to design slide presentations.

Related

Abstracting Lists in Dr. Racket

Currently, I have a function item counts that is meant to count the number of elements in a string and order them into pairs if it occurs once or more.
(check-expect
(item-counts
(cons "hello"
(cons "hey"
(cons "hello" '())))
equal?)
(cons "hello" 2
(cons "hey" 1) '()))
(check-expect
(item-counts
(cons #true
(cons #false
(cons #true '())))
equal?)
(cons #true 2
(cons #false 1 '())))
(define (item-counts lop ef)
(cond
[(empty? (rest lop))
(first lop)]
[(cons? (rest lop))
(if
(ef (first lop) (item-counts (rest lop) ef))) ... ???
As shown by the tests, I wish to add a number to the existing list if one of the elements of this list occurs more than once. I used the equal? function to identify the number of times an element occurs, but I am lost on how to add the number to the existing list as well as condense the repeating elements when producing a new list. I have tried using the append function but it creates a list in a different format ( (list (list) ).
I don't know if this is self-learning, for a class, etc. I know there are standard HtDP ways to do this, recipes, etc. But I don't know these things, sorry. What I will say is that Racket is quite easy to prototype things. You can just describe your problem and don't think too much about the details. I usually like to start in the middle.
For example:
At some point in the middle of execution you will have strings yet to examine and an association list of the strings examined so far. Then your task is 1) if there are no more strings to get, we're done, otherwise 2) get the next string, add it to the table, and continue because we're not done.
(define (build-assoc from-string current-assoc)
(if (done? from-string)
current-assoc
(let ((first-string (get-first-string from-string)))
(let ((result-table (add-string first-string current-assoc))
(result-string (drop-first-string from-string)))
(build-assoc result-string
result-table)))))
Maybe you don't use this procedure in the end. But it's a picture of what you're doing, and it suggests what sort of helper procedures you will need to finish your quest. Give yourself a fighting chance and just use DrRacket to outline your problem. When you see it, then maybe it gives you some ideas how to answer the questions. DrRacket helpfully points out all your unanswered questions like "done?: unbound identifier in: done?" Ah yes, how do we know we're done, good question DrRacket. Well you see, I was given this list of strings, so...

Racket (Recursive structures and processing templates)

I'm stumped on processing this structure, I want to write a function that tells how many topics occur in a discussion.
; a Discussion is (make-discussion String Digressions)
(define-struct discussion [topic digressions])
; Digressions is [ListOf Discussion]
; count-topics : Discussion -> Number
; counts the number of total topics in a discussion, including repeated topics
(define (count-topics d)
(cond
[(empty? (discussion-digressions d)) 0]
[(cons? (discussion-digressions d)) (add1 (count-topics (make-discussion (first (discussion-topic d))
(list (make-discussion (rest (discussion-digressions d)))))))]))
(check-expect (count-topics (make-discussion "music" (list (make-discussion "politics" empty)))) 2)
I've been trying for a few hours and haven't solved it yet. I'm not sure where to go from here, anybody have a sharp eye for Racket? I've tried to process the topic first, but haven't had any luck doing it that way.
You should not use make-discussion in your solution, we're trying to traverse the structures, not to create new ones. There are two cases to consider:
If the digressions list is empty, then we've found one topic, and there's nowhere else to go.
Otherwise, we count one topic (the current one) and call the recursion over all the elements in the list of digressions, adding their results. This is easy to implement using apply and map
This is what I mean:
(define (count-topics d)
(cond
[(empty? (discussion-digressions d)) 1]
[else (add1 (apply + (map count-topics (discussion-digressions d))))]))
Of course you can solve this without using apply and map, but for that it's better to write separate procedures as Alex suggests. Anyway, my approach works as expected:
(count-topics
(make-discussion "music"
(list (make-discussion "politics" empty))))
=> 2

Common Lisp: unable to get the uncompress function in Paul Graham's book working

Lisp newbie here.
I am reading Paul Graham's book, ANSI Common Lisp.
On page 38 is an uncompress function. It takes a list of pairs, where the first item in the pair is a number to indicate how many of the second item there should be. For example, uncompressing this:
((3 a) (2 b) c)
should produce this:
(A A A B B C)
I typed the uncompress function into a Lisp interpreter (GCL-2.6.2-ANSI) and then tested it like this:
(uncompress '((3 A) B (2 C) (5 D)))
That produced this error message:
Error in IF [or a callee]: Too many arguments.
Fast links are on: do (use-fast-links nil) for debugging
Broken at IF. Type :H for Help.
1 (Abort) Return to top level.
Below is the uncompress function. I think that I faithfully typed what was written in the book. I have tested each piece and each piece seems to work correctly. Truthfully, I'm stuck. I don't know what's causing the error. I'd appreciate your help.
(defun uncompress (lst)
(if (null lst)
nil
(let (elt (car lst))
(rest (uncompress (cdr lst))))
(if (consp elt)
(append (apply #'list-of elt)
rest)
(cons elt rest))))
(defun list-of (n elt)
(if (zerop n)
nil
(cons elt (list-of (- n 1) elt))))
If you use editor indentation tools, the code looks like this:
(defun uncompress (lst)
(if (null lst)
nil
(let (elt (car lst))
(rest (uncompress (cdr lst))))
(if (consp elt)
(append (apply #'list-of elt)
rest)
(cons elt rest))))
That would have made it easier to spot this error. Syntactically it is wrong, since the IF does not take more than three forms.
(defun uncompress (lst)
(if (null lst) ; the IF has four subforms, one too many
nil
(let (elt (car lst)) ;<- variables ELT and CAR? Makes no sense
(rest (uncompress (cdr lst)))) ; <- not using the result?
(if (consp elt) ; <- fourth form in IF? Does not make sense.
(append (apply #'list-of elt)
rest)
(cons elt rest))))
In Common Lisp both IF and LET are special operators with built-in syntax.
In Lisp the syntax for LET usually is:
let ({var | (var [init-form])}*) form* => result*
In Common Lisp it is possible to add declarations on top of the body forms of the LET:
let ({var | (var [init-form])}*) declaration* form* => result*
The syntax for IF in Common Lisp is:
if test-form then-form [else-form] => result*
Indentation
Generally it is not a good idea to manually indent Lisp code. Let the editor or IDE do it. Make sure that all code is properly indented.
If you have a syntax problem: first re-indent the expression -> this makes sure that the code is properly indented and then makes finding problems easier. Next compile the code and read the compiler error message. Common Lisp has great compilers and some have quite good error reporting.
The code
The code is not great anyway: it uses recursion where higher-order functions exist or a LOOP would be better
This version got both: the higher-order MAPCAN and a LOOP:
(defun uncompress (list)
(mapcan #'expand-item list))
(defun expand-item (item)
(typecase item
(atom (list item))
(cons (destructuring-bind (n element) item
(loop repeat n collect element)))))
You have the most typical common lisp syntax error: incorrect use of parentheses!
Here is the correct version:
(defun uncompress (lst)
(if (null lst)
nil
(let ((elt (car lst))
(rest (uncompress (cdr lst))))
(if (consp elt)
(append (apply #'list-of elt)
rest)
(cons elt rest)))))
Since these kind of errors are so common when no specialized editor is used, I advise you to use an editor like Emacs or Vim to edit your programs.

Lisp in Small Pieces. chapter 1

I began to study the book "Lisp in Small Pieces". For examples, the selected Racket. But in the first chapter there is a code sample (if (atom? e) . What is "atom?"? Where to define it?
The Scheme standard does not define atom?; the usual definition is
(define (atom? x)
(and (not (pair? x))
(not (null? x))))

First larger (common) lisp program -> 'random' not working as expected

just for fun I wrote a simulation of the "monty hall problem" in Python. Later I experimented with Lua and decided to write it again in Lua to see how it will look in comparison. It was a quite interesting experience even though the programs looked very similar (the Lua version was slightly shorter). Lately I started to exeriment with CL and wanted to do the same thing again. However when I run it, it does not behave as expected. For some reason the erratic player (who should get a 66% chance to win) has almost the same score as the naive player (with 50 % chance to win).
Can someone please give me a hint what is going wrong? This is not a homework or something like that, just my first try to write a larger program with CL. Besides hints regarding the problem described above I would also welcome suggestions on how to improve my style. I guess that it's still pretty Python-ish (it's more or less a direct translation).
(defun choose-one (l)
"Ramdomly chooses one element of the given list"
(nth (random (length l)) l))
(defun remove-one (l)
"Randomly removes one element of the given list"
(remove (choose-one l) l))
(defun naive-player (initial-choice possible-choices)
"The naive player randomly picks one choice. Should have a 50% chance to win."
initial-choice ;keep compiler happy
(choose-one possible-choices))
(defun stubborn-player (initial-choice possible-choices)
"The stubborn player sticks with his initial choice. Should have a 33% chance to win."
possible-choices ;keep compiler happy
initial-choice)
(defun erratic-player (initial-choice possible-choices)
"The erratic player will always change his choice. Should have a 66% chance to win."
(choose-one (remove initial-choice possible-choices)))
(defun host-offer (prize possible-choices)
"The host reveals one wrong choice."
(let ((remaining (remove prize possible-choices)))
(remove (choose-one remaining) possible-choices)))
(defun one-game (playerfn choices)
"Simulates a single game with the given player. Evaluates to T if the player won."
(let ((prize (choose-one choices))
(player-choice (choose-one choices)))
(eq (funcall playerfn player-choice (host-offer prize choices)) prize)))
(defun multiple-games (num-games)
"Simulates the given number of games with all players. Evaluates to a result list."
(let ((choices '(door_a door_b door_c))
(naive-score 0)
(stubborn-score 0)
(erratic-score 0))
;(progn
(dotimes (i num-games)
;(progn
(if (one-game #'naive-player choices)
(incf naive-score))
(if (one-game #'stubborn-player choices)
(incf stubborn-score))
(if (one-game #'erratic-player choices)
(incf erratic-score)));)
(list
(list 'naive-player naive-score)
(list 'stubborn-player stubborn-score)
(list 'erratic-player erratic-score))));)
;; Run simulation and display results
(defparameter *num-games* 10000)
(format *standard-output* "--- Monty Hall ---~%")
(format *standard-output* "Simulating ~D games...~%" *num-games*)
(let ((result (multiple-games *num-games*)))
(format *standard-output* "~{~{~A score: ~D~}~%~}" result))
Output (for example):
--- Monty Hall ---
Simulating 10000 games...
NAIVE-PLAYER score: 5014
STUBBORN-PLAYER score: 3333
ERRATIC-PLAYER score: 4968
The host offer function is wrong. In the Monty Hall problem as defined the host will never open the door the player has chosen, but your program doesn't take that into account. If that is fixed the program returns expected results.