Skip to content

Instantly share code, notes, and snippets.

@simon-brooke
Created July 12, 2017 21:46
Show Gist options
  • Save simon-brooke/9f42f5530c1db1b6e81e6d196c6a45f1 to your computer and use it in GitHub Desktop.
Save simon-brooke/9f42f5530c1db1b6e81e6d196c6a45f1 to your computer and use it in GitHub Desktop.
Mountain sort: sort the largest elements in a sequence to the middle
;; gorilla-repl.fileformat = 1
;; **
;;; # Mountain Sort
;;;
;;; A sorting function that sorts largest to the middle.
;;;
;;; ## A bit about Gorilla Repl
;;;
;;; This file was written in, and can be run and edited in,
;;; [Gorilla Repl](http://gorilla-repl.org/index.html).
;;; The code, however, is perfectly ordinary Clojure code.
;;;
;;; If running in Gorilla Repl, shift + enter evaluates code.
;;; Hit ctrl+g twice in quick succession or click the menu icon
;;; (upper-right corner) for more commands ...
;; **
;; @@
(ns cc.journeyman.mountain-sort)
;; @@
;; =>
;;; {"type":"html","content":"<span class='clj-nil'>nil</span>","value":"nil"}
;; <=
;; **
;;; ## Introduction
;;;
;;; I was writing a swingometer for someone, for use in televised
;;; election coverage. The customer looked at the demo, and said
;;; "it's nice, but it would be better if the biggest parties were
;;; always in the middle."
;;;
;;; So I wrote a quick and dirty function to do that sort, and then
;;; realised it would be really easy to generalise. So here's
;;; **mountain-sort**:
;; **
;; @@
(defn- in-mountain-sort
"Internal function to mountain-sort; not public. Divide this
`sorted-sequence` into even and odd sub-sequences, and return
these concatenated back to back."
[sorted-sequence]
(concat (take-nth 2 sorted-sequence)
(reverse (take-nth 2 (rest sorted-sequence)))))
(defn mountain-sort
"Sort this `sequence` so that the largest are in the middle."
([sequence]
(let [first-sort (sort sequence)]
(in-mountain-sort first-sort)))
([sequence accessor-fn]
(let [first-sort (sort-by accessor-fn sequence)]
(in-mountain-sort first-sort))))
;; @@
;; =>
;;; {"type":"html","content":"<span class='clj-var'>#&#x27;cc.journeyman.mountain-sort/mountain-sort</span>","value":"#'cc.journeyman.mountain-sort/mountain-sort"}
;; <=
;; **
;;; ## mountain-sort sorts simple things
;;;
;;; Sometimes the things we want to sort are just simple.
;; **
;; @@
(mountain-sort (range 0 11))
;; @@
;; =>
;;; {"type":"list-like","open":"<span class='clj-lazy-seq'>(</span>","close":"<span class='clj-lazy-seq'>)</span>","separator":" ","items":[{"type":"html","content":"<span class='clj-long'>0</span>","value":"0"},{"type":"html","content":"<span class='clj-long'>2</span>","value":"2"},{"type":"html","content":"<span class='clj-long'>4</span>","value":"4"},{"type":"html","content":"<span class='clj-long'>6</span>","value":"6"},{"type":"html","content":"<span class='clj-long'>8</span>","value":"8"},{"type":"html","content":"<span class='clj-long'>10</span>","value":"10"},{"type":"html","content":"<span class='clj-long'>9</span>","value":"9"},{"type":"html","content":"<span class='clj-long'>7</span>","value":"7"},{"type":"html","content":"<span class='clj-long'>5</span>","value":"5"},{"type":"html","content":"<span class='clj-long'>3</span>","value":"3"},{"type":"html","content":"<span class='clj-long'>1</span>","value":"1"}],"value":"(0 2 4 6 8 10 9 7 5 3 1)"}
;; <=
;; @@
(mountain-sort ["alpha" "bravo" "charlie" "delta" "echo" "foxtrot" "golf" "hotel" "india" "juliet"])
;; @@
;; =>
;;; {"type":"list-like","open":"<span class='clj-lazy-seq'>(</span>","close":"<span class='clj-lazy-seq'>)</span>","separator":" ","items":[{"type":"html","content":"<span class='clj-string'>&quot;alpha&quot;</span>","value":"\"alpha\""},{"type":"html","content":"<span class='clj-string'>&quot;charlie&quot;</span>","value":"\"charlie\""},{"type":"html","content":"<span class='clj-string'>&quot;echo&quot;</span>","value":"\"echo\""},{"type":"html","content":"<span class='clj-string'>&quot;golf&quot;</span>","value":"\"golf\""},{"type":"html","content":"<span class='clj-string'>&quot;india&quot;</span>","value":"\"india\""},{"type":"html","content":"<span class='clj-string'>&quot;juliet&quot;</span>","value":"\"juliet\""},{"type":"html","content":"<span class='clj-string'>&quot;hotel&quot;</span>","value":"\"hotel\""},{"type":"html","content":"<span class='clj-string'>&quot;foxtrot&quot;</span>","value":"\"foxtrot\""},{"type":"html","content":"<span class='clj-string'>&quot;delta&quot;</span>","value":"\"delta\""},{"type":"html","content":"<span class='clj-string'>&quot;bravo&quot;</span>","value":"\"bravo\""}],"value":"(\"alpha\" \"charlie\" \"echo\" \"golf\" \"india\" \"juliet\" \"hotel\" \"foxtrot\" \"delta\" \"bravo\")"}
;; <=
;; **
;;; ## mountain-sort also sorts more complex things
;;;
;;; But generally the things we want to sort are more complex, like
;;; records of some kind. The particular records I wanted to sort were
;;; election outcomes. Here's the data:
;; **
;; @@
(def election-data
{:snp {:id :snp :name "Scottish National Party" :colour "yellow" :votes 16701}
:lab {:id :lab :name "Labour Party" :colour "red" :votes 10775}
:con {:id :con :name "Conservative Party" :colour "blue" :votes 22344}
:ld {:id :ld :name "Liberal Democrats" :colour "GoldenRod" :votes 1241}
:ind {:id :ind :name "Independent" :colour "DarkViolet" :votes 538}})
;; @@
;; =>
;;; {"type":"html","content":"<span class='clj-var'>#&#x27;cc.journeyman.mountain-sort/election-data</span>","value":"#'cc.journeyman.mountain-sort/election-data"}
;; <=
;; @@
(mountain-sort (vals election-data) :votes)
;; @@
;; =>
;;; {"type":"list-like","open":"<span class='clj-lazy-seq'>(</span>","close":"<span class='clj-lazy-seq'>)</span>","separator":" ","items":[{"type":"list-like","open":"<span class='clj-map'>{</span>","close":"<span class='clj-map'>}</span>","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:id</span>","value":":id"},{"type":"html","content":"<span class='clj-keyword'>:ind</span>","value":":ind"}],"value":"[:id :ind]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:name</span>","value":":name"},{"type":"html","content":"<span class='clj-string'>&quot;Independent&quot;</span>","value":"\"Independent\""}],"value":"[:name \"Independent\"]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:colour</span>","value":":colour"},{"type":"html","content":"<span class='clj-string'>&quot;DarkViolet&quot;</span>","value":"\"DarkViolet\""}],"value":"[:colour \"DarkViolet\"]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:votes</span>","value":":votes"},{"type":"html","content":"<span class='clj-long'>538</span>","value":"538"}],"value":"[:votes 538]"}],"value":"{:id :ind, :name \"Independent\", :colour \"DarkViolet\", :votes 538}"},{"type":"list-like","open":"<span class='clj-map'>{</span>","close":"<span class='clj-map'>}</span>","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:id</span>","value":":id"},{"type":"html","content":"<span class='clj-keyword'>:lab</span>","value":":lab"}],"value":"[:id :lab]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:name</span>","value":":name"},{"type":"html","content":"<span class='clj-string'>&quot;Labour Party&quot;</span>","value":"\"Labour Party\""}],"value":"[:name \"Labour Party\"]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:colour</span>","value":":colour"},{"type":"html","content":"<span class='clj-string'>&quot;red&quot;</span>","value":"\"red\""}],"value":"[:colour \"red\"]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:votes</span>","value":":votes"},{"type":"html","content":"<span class='clj-long'>10775</span>","value":"10775"}],"value":"[:votes 10775]"}],"value":"{:id :lab, :name \"Labour Party\", :colour \"red\", :votes 10775}"},{"type":"list-like","open":"<span class='clj-map'>{</span>","close":"<span class='clj-map'>}</span>","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:id</span>","value":":id"},{"type":"html","content":"<span class='clj-keyword'>:con</span>","value":":con"}],"value":"[:id :con]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:name</span>","value":":name"},{"type":"html","content":"<span class='clj-string'>&quot;Conservative Party&quot;</span>","value":"\"Conservative Party\""}],"value":"[:name \"Conservative Party\"]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:colour</span>","value":":colour"},{"type":"html","content":"<span class='clj-string'>&quot;blue&quot;</span>","value":"\"blue\""}],"value":"[:colour \"blue\"]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:votes</span>","value":":votes"},{"type":"html","content":"<span class='clj-long'>22344</span>","value":"22344"}],"value":"[:votes 22344]"}],"value":"{:id :con, :name \"Conservative Party\", :colour \"blue\", :votes 22344}"},{"type":"list-like","open":"<span class='clj-map'>{</span>","close":"<span class='clj-map'>}</span>","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:id</span>","value":":id"},{"type":"html","content":"<span class='clj-keyword'>:snp</span>","value":":snp"}],"value":"[:id :snp]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:name</span>","value":":name"},{"type":"html","content":"<span class='clj-string'>&quot;Scottish National Party&quot;</span>","value":"\"Scottish National Party\""}],"value":"[:name \"Scottish National Party\"]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:colour</span>","value":":colour"},{"type":"html","content":"<span class='clj-string'>&quot;yellow&quot;</span>","value":"\"yellow\""}],"value":"[:colour \"yellow\"]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:votes</span>","value":":votes"},{"type":"html","content":"<span class='clj-long'>16701</span>","value":"16701"}],"value":"[:votes 16701]"}],"value":"{:id :snp, :name \"Scottish National Party\", :colour \"yellow\", :votes 16701}"},{"type":"list-like","open":"<span class='clj-map'>{</span>","close":"<span class='clj-map'>}</span>","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:id</span>","value":":id"},{"type":"html","content":"<span class='clj-keyword'>:ld</span>","value":":ld"}],"value":"[:id :ld]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:name</span>","value":":name"},{"type":"html","content":"<span class='clj-string'>&quot;Liberal Democrats&quot;</span>","value":"\"Liberal Democrats\""}],"value":"[:name \"Liberal Democrats\"]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:colour</span>","value":":colour"},{"type":"html","content":"<span class='clj-string'>&quot;GoldenRod&quot;</span>","value":"\"GoldenRod\""}],"value":"[:colour \"GoldenRod\"]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":"<span class='clj-keyword'>:votes</span>","value":":votes"},{"type":"html","content":"<span class='clj-long'>1241</span>","value":"1241"}],"value":"[:votes 1241]"}],"value":"{:id :ld, :name \"Liberal Democrats\", :colour \"GoldenRod\", :votes 1241}"}],"value":"({:id :ind, :name \"Independent\", :colour \"DarkViolet\", :votes 538} {:id :lab, :name \"Labour Party\", :colour \"red\", :votes 10775} {:id :con, :name \"Conservative Party\", :colour \"blue\", :votes 22344} {:id :snp, :name \"Scottish National Party\", :colour \"yellow\", :votes 16701} {:id :ld, :name \"Liberal Democrats\", :colour \"GoldenRod\", :votes 1241})"}
;; <=
;; **
;;; ## That's all folks!
;; **
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment