Created
July 12, 2017 21:46
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; 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'>#'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'>"alpha"</span>","value":"\"alpha\""},{"type":"html","content":"<span class='clj-string'>"charlie"</span>","value":"\"charlie\""},{"type":"html","content":"<span class='clj-string'>"echo"</span>","value":"\"echo\""},{"type":"html","content":"<span class='clj-string'>"golf"</span>","value":"\"golf\""},{"type":"html","content":"<span class='clj-string'>"india"</span>","value":"\"india\""},{"type":"html","content":"<span class='clj-string'>"juliet"</span>","value":"\"juliet\""},{"type":"html","content":"<span class='clj-string'>"hotel"</span>","value":"\"hotel\""},{"type":"html","content":"<span class='clj-string'>"foxtrot"</span>","value":"\"foxtrot\""},{"type":"html","content":"<span class='clj-string'>"delta"</span>","value":"\"delta\""},{"type":"html","content":"<span class='clj-string'>"bravo"</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'>#'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'>"Independent"</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'>"DarkViolet"</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'>"Labour Party"</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'>"red"</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'>"Conservative Party"</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'>"blue"</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'>"Scottish National Party"</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'>"yellow"</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'>"Liberal Democrats"</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'>"GoldenRod"</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