Select featured exercises for Summer of Sexps

Next month (June), will have the Summer of Sexps theme, where we’ll feature the following LISP dialects:

  • Clojure
  • ClojureScript
  • Common Lisp
  • Emacs Lisp
  • Racket
  • Scheme

On the surface, these languages look quite alike, but there are of course differences (e.g. Clojure runs on the JVM and has a dedicated map type, Common Lisp supports OOP and Racket is great for DSLs).

It would be great if we could find exercises that, even though the languages are similar, can be solved differently.
If we can select exercises that haven’t yet been used, that would be lovely.

Here is the list of shared exercises.
Note: in this case, I think porting missing exercises should be more straightforward than before due to the similar syntax, so I don’t mind choosing some exercises that are not implemented by all tracks.

exercise clojure clojurescript common-lisp emacs-lisp racket scheme
acronym :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
anagram :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
armstrong-numbers :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
atbash-cipher :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
bob :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
difference-of-squares :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
grains :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
hamming :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
hello-world :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
leap :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
matching-brackets :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
nucleotide-count :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
perfect-numbers :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
phone-number :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
raindrops :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
rna-transcription :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
robot-name :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
roman-numerals :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
two-fer :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
word-count :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
all-your-base :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :x:
allergies :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :x:
collatz-conjecture :white_check_mark: :white_check_mark: :white_check_mark: :x: :white_check_mark: :white_check_mark:
etl :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :x:
gigasecond :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :x:
pangram :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :x: :white_check_mark:
queen-attack :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :x: :white_check_mark:
rotational-cipher :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :x: :white_check_mark:
scrabble-score :white_check_mark: :white_check_mark: :white_check_mark: :x: :white_check_mark: :white_check_mark:
sublist :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :x:
triangle :white_check_mark: :white_check_mark: :white_check_mark: :x: :white_check_mark: :white_check_mark:
accumulate :white_check_mark: :white_check_mark: :x: :x: :white_check_mark: :white_check_mark:
affine-cipher :x: :x: :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark:
binary-search :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :white_check_mark:
crypto-square :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :x: :x:
isogram :white_check_mark: :white_check_mark: :white_check_mark: :x: :white_check_mark: :x:
luhn :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :x: :x:
meetup :white_check_mark: :white_check_mark: :white_check_mark: :x: :white_check_mark: :x:
pascals-triangle :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :white_check_mark:
prime-factors :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :white_check_mark:
run-length-encoding :white_check_mark: :white_check_mark: :white_check_mark: :white_check_mark: :x: :x:
say :white_check_mark: :white_check_mark: :white_check_mark: :x: :white_check_mark: :x:
sieve :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :white_check_mark:
strain :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :white_check_mark:
sum-of-multiples :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :white_check_mark:
trinary :white_check_mark: :x: :white_check_mark: :white_check_mark: :x: :white_check_mark:
beer-song :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :x:
binary :white_check_mark: :x: :white_check_mark: :white_check_mark: :x: :x:
change :white_check_mark: :white_check_mark: :x: :x: :x: :white_check_mark:
darts :x: :x: :white_check_mark: :white_check_mark: :white_check_mark: :x:
diamond :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :x:
flatten-array :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :x:
grade-school :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :x:
isbn-verifier :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :x:
largest-series-product :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :x:
list-ops :x: :x: :x: :white_check_mark: :white_check_mark: :white_check_mark:
nth-prime :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :x:
pig-latin :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :x:
protein-translation :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :x:
proverb :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :x:
reverse-string :white_check_mark: :white_check_mark: :x: :x: :white_check_mark: :x:
robot-simulator :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :x:
secret-handshake :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :x:
space-age :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :x:
spiral-matrix :white_check_mark: :white_check_mark: :white_check_mark: :x: :x: :x:
bank-account :white_check_mark: :white_check_mark: :x: :x: :x: :x:
binary-search-tree :white_check_mark: :white_check_mark: :x: :x: :x: :x:
clock :white_check_mark: :white_check_mark: :x: :x: :x: :x:
complex-numbers :white_check_mark: :white_check_mark: :x: :x: :x: :x:
dominoes :white_check_mark: :white_check_mark: :x: :x: :x: :x:
go-counting :white_check_mark: :white_check_mark: :x: :x: :x: :x:
kindergarten-garden :white_check_mark: :white_check_mark: :x: :x: :x: :x:
knapsack :x: :x: :white_check_mark: :x: :x: :white_check_mark:
minesweeper :white_check_mark: :white_check_mark: :x: :x: :x: :x:
octal :white_check_mark: :x: :x: :x: :x: :white_check_mark:
poker :white_check_mark: :white_check_mark: :x: :x: :x: :x:
pov :white_check_mark: :white_check_mark: :x: :x: :x: :x:
rail-fence-cipher :x: :x: :white_check_mark: :white_check_mark: :x: :x:
series :white_check_mark: :white_check_mark: :x: :x: :x: :x:
twelve-days :x: :x: :white_check_mark: :x: :white_check_mark: :x:
wordy :white_check_mark: :white_check_mark: :x: :x: :x: :x:
yacht :white_check_mark: :white_check_mark: :x: :x: :x: :x:
zipper :white_check_mark: :white_check_mark: :x: :x: :x: :x:
alphametics :x: :x: :x: :x: :white_check_mark: :x:
book-store :x: :x: :white_check_mark: :x: :x: :x:
food-chain :x: :x: :white_check_mark: :x: :x: :x:
forth :x: :x: :x: :x: :x: :white_check_mark:
grep :x: :x: :x: :x: :white_check_mark: :x:
hexadecimal :white_check_mark: :x: :x: :x: :x: :x:
house :x: :x: :x: :x: :white_check_mark: :x:
matrix :x: :x: :white_check_mark: :x: :x: :x:
palindrome-products :x: :x: :white_check_mark: :x: :x: :x:
pythagorean-triplet :x: :x: :white_check_mark: :x: :x: :x:
saddle-points :x: :x: :white_check_mark: :x: :x: :x:
simple-cipher :x: :x: :x: :white_check_mark: :x: :x:
transpose :x: :x: :x: :x: :x: :white_check_mark:
two-bucket :x: :x: :white_check_mark: :x: :x: :x:
variable-length-quantity :x: :x: :x: :x: :white_check_mark: :x:

I think collatz, sublist, and accumulate would be good candidates.

1 Like

I consider accumulate, but it is actually a deprecated exercise. It is also missing from two tracks and I’d prefer not to add new deprecated exercises.

collatz-conjecture has already been featured (in February). This is not a deal-breaker per se, but I would like to avoid duplicates when possible. One benefit of collatz-conjecture is that it is great for practicing recursion.

Personally, I’m not a fan of sublist :person_shrugging:

My initial selection was:

leap: boolean conditions, truthiness, possible lexical scoping due to nested helper function
two-fer: optional values, handled differently across the tracks
difference-of-squares: math/prefix notation, ranges
robot-name: randomness, strings and potentially OO
anagram: strings as lists of characters

What do you think about that list? I’ve tried to select these exercises based on a couple of criteria:

  1. They can’t be too hard. Lisps are quite different from other tracks, so I think using simpler exercises works best this month
  2. I want students to use some lisp-specific idioms (prefix notation, especially when doing math, recursion, list processing)
  3. The exercises are solved somewhat differently across the featured tracks
  4. The exercises must be implemented by the majority of the features tracks

I might replace one of these with collatz-conjecture for working with recursion.

1 Like

The main reasons I picked the three were recursion and how lists work. While working with clojure, I found it quite elementary to understand the many related functions and concepts. I have not done the sublist exercise in a while and selected it purely from what I remember.

Accumulate I had selected as a prime candidate to practice folding, but deprecated exercises have a reason to be deprecated.

I agree that folding is not an easy concept and might put some people off. Once I got it my mind was blown away :D

1 Like

I agree that a list-processing exercise makes sense. The list-ops exercise has superseded the accumulate exercise, but that does include folds. What about strain? It’s not yet implemented in Racket and Emacs Lisp, but it does have a couple of things going for it:

  • Doing list processing
  • Not being too complicated
  • Working with recursion
1 Like

Do we have evidence that List Ops is too hard?

I favor List Ops because it features all the interestingness of Accumulate, Strain, &c. It is a very Lisp-y exercise (as far as I know having its origins in this family), and can be very educational. Its description could perhaps use some explanatory examples of the folds.

I do from mentoring experience. Maybe others could chime in.

It has a “rather low” completion rate on the racket track, thus I would put it in the advanced tier.

Strain is very reduced compared to list-ops. I like list-ops because it really covers a lot of nice functional programming, that transfers nicely to other languages. But it is indeed on the heavy side of exercises. Maybe some ramped up docs would help to guide students and boost the completion rate?

Strain is basically a “make a filter” and can be solved in very unidiomatic ways, but would work for people who just want to scratch the surface. If they opt to get a mentor, they would surely show the students how to improve.

Okay, suppose we went with list-ops. We would need to implement it in Clojure and Common Lisp at the very least, as those are likely our biggest Lisp tracks right now. Would anybody be up for that?

I don’t know if @porkostomus has some time for that, but with some reading, I might be able to support

Note that the Common Lisp track has foregone the list-ops exercise, although I don’t agree with the reasoning: Updated foregone exercises in config.json by PaulT89 · Pull Request #614 · exercism/common-lisp · GitHub
You can avoid the name conflicts with existing functions by using a prefix.

I think list-ops is a great way to try out the high-order function capabilities of a language. Although I admit that it’s hard to wrap your head around it the first time.

@verdammelt Would you reconsider?

Regarding robot-name and OO: Common Lisp and Emacs Lisp come with OO-capabilities but both tracks test against a non-OO API, so while it’s possible to internally implement it using the OO libraries the students don’t get forced into that direction. Maybe that’s also a good thing? Wdyt?

Yes I think that’s perfectly fine!

We would need to implement it in Clojure

I don’t know if @porkostomus has some time for that

Yes I could port this this week :slight_smile:

1 Like

List ops may be a great exercise, but it’s a bit of a stretch for beginners. It’s lengthy, that means it demands a lot of time and effort from someone who just started coding. People tend to avoid those exercises just because they end up being tedious.

Another problem is that the exercise does not exist in Clojure meaning not many people will bother with mentoring. Even worse, mentors tend to avoid lengthy solutions.

I have the exercise bootstrapped and the test suite is almost should be done:

List ops exercise by bobbicodes · Pull Request #552 · exercism/clojure (github.com)

I suppose the next task is to solve it! Alternatively… I could just submit an example solution that “cheats”, i.e. uses library functions like map, filter, etc.

2 Likes

As a possible alternative, I think matching-brackets admits a nice, LISP-y solution using a(n) accumulate/fold/reduce/what-have-you. According to that table, it’s implemented in all tracks, and it hasn’t been featured in any previous month, either!

How could I miss that - such a classic!

1 Like

What do you think @porkostomus about using matching-brackets? BTW, having list-ops is still a great exercise regardless if we use it.

1 Like