32

Introduction to Code-Golf in Clojure

 5 years ago
source link: https://bfontaine.net/blog/2019/12/01/introduction-to-code-golf-in-clojure/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Code-Golf is the art of writing the shortest program in a given language that implements some given algorithm. It started in the 90’s in the Perl community and spread to other languages; there are now languages dedicated to code-golfing and StackExchange has a Q&A website for it.

In 2015, for example, I wrote a blog post showing how to write a JavaScript modules manager that fits in 140 chars (the maximum length of a tweet at that time).

4clojure is a well-known website to learn Clojure through exercises of increasing difficulty, but it has a lesser-known code-golf challenge which you can enable by clicking on “ Leagues ” in the top menu. If you check the code-golf checkbox, you then get a score on each problem that is the number of non-whitespace characters of your solution; the smaller the better.

The first thing you’ll note when code-golfing is that the reader syntax for anonymous functions is a lot shorter than using fn :

; 18 chars
(fn [a b c] (* (+ a b) c))

; 13 chars
#(* (+ %1 %2) %3)
; 12 chars: -1 char because '%' is equivalent to '%1'
#(* (+ % %2) %3)

Unfortunately you can’t have a reader-syntax function inside another reader-syntax one, so you often have to transform the code not to use anonymous functions.

for is a very powerful tool for that, because it allows you to do the equivalent of map , and a lot more, with no function:

; invalid!
#(map #(* 2 %) %)

; 19 chars
#(map (fn [x] (* 2 x)) %)
; 17 chars
#(map (partial * 2) %)
; 15 chars
#(for [x %] (* 2 x))

; Note that for this specific example
; the best solution uses `map`:
#(map + % %)

On some problems it can even be shorter than using map + filter :

; 31 chars
(fn [x a]
  (map inc (filter #(< % a) x)))

; 26 chars
#(for [e x :when (< e a)] (inc e))

Some core functions are equivalent in some contexts and so the shorter one can substitute a longer one:

; 18 chars
#(filter identity %)
; 14 chars
#(filter comp %)

; 6 chars
(inc x)
(dec x)
; 5 chars
(+ x 1)
(- x 1)

; 12 chars
(reduce str x)
; 11 chars
(apply str x)

; 14 chars
(apply concat x)
; 13 chars
(mapcat comp x)

When you must use a long function name in multiple places, it might be shorter to let that function with a one-letter symbol:

; 120 chars
#(clojure.set/difference
   (clojure.set/union % %2)
   (clojure.set/union
     (clojure.set/difference % %2)
     (clojure.set/difference %2 %)))

; 73 chars
#(let [d clojure.set/difference u clojure.set/union]
   (d (u % %2) (u (d % %2) (d %2 %))))

; Note that for this specific example
; there is a 17-chars solution
#(set (filter %2 %))

Other tricks

Use indexed access on vectors:

; 15 chars
(first [:a :b :c])
; 11 chars
([:a :b :c] 0)

Use set literals as functions:

; 16 chars
(remove #(= :a %) x)
; 14 chars
(remove #{:a} x)

Inverse conditions to use shorter functions:

; 15 chars
(if (empty? p) a b)
; 12 chars
(if (seq p) b a)

Inlined code is sometimes shorter:

; 24 chars
(let [p (* 3 a)]
  (if (< p 5)
    a
    p))
; 19 chars
(if (< (* 3 a) 5)
  a
  (* 3 a))

Use 1 instead of :else / :default in cond :

; 24 chars
(cond
  (= m p) a
  (< m p) b
  :else c)

; 20 chars
(cond
  (= m p) a
  (< m p) b
  1 c)

Use maps instead of if s for conditions on equality (this one really makes the code harder to read):

; 13 chars
(if (= "L" x) a b)
; 12 chars
(case x "L" a b)
; 10 chars
({"L" a} x b)

Recommend

  • 132
    • www.promptworks.com 7 years ago
    • Cache

    Connect "Fore!": Code Golf in Javascript

    Connect "Fore!": Code Golf in JavascriptTest and expand your Javascript knowledge with this fun challenge.September 25, 2017by Peter Caisse

  • 78
    • code-golf.io 7 years ago
    • Cache

    Code-Golf

    Code Golf Code Golf is a game designed to let you show off your code-fu by solving problems in the least number of characters. Since this is your f...

  • 76
    • www.tuicool.com 6 years ago
    • Cache

    Code Golf: Sparse Arrays

    Today on Twitter, Axel Rauschmayer posted a fun little coding challenge: Code golf: check if an Array has holes. I’ll reply with two ideas of mine in a f...

  • 36
    • code-golf.io 4 years ago
    • Cache

    Code Golf

    Code Golf Code Golf is a game designed to let you show off your code-fu by solving problems in the least number of characters. Since this is your first time he...

  • 13
    • bsless.github.io 4 years ago
    • Cache

    Idiomatic Clojure: Code Smells

    We all make mistakes. We have all written bad pieces of code at some point of our lives. They might have been non-idiomatic, unreadable, or had bad performance. This post catalogs all the little things which sit do...

  • 16

    PowerShell 10 Year Anniversary Code Golf Winners For the PowerShell 10 Year Anniversary, Will Anderson (@GamerLivingWill on Twitter) and I (

  • 9

    Recursions without names: Introduction to the Y combinator in clojure Aug 7, 2016 • Yehonathan Sharvit This is an introductory article to the

  • 9

    Code a Spectrum-style Crazy Golf game | Wireframe #54 Putt the ball around irrational obstacles in our retro take on golf. Mark Vanstone has the code First released by...

  • 6

    Code Golf Code Golf is a game designed to let you show off your code-fu by solving problems in the least number of characters. Since this is your first...

  • 5
    • markm208.github.io 1 year ago
    • Cache

    An Animated Introduction to Clojure

    An Animated Introduction to Clojure Mark Mahoney

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK