I'm trying to run the following code.
Below are the steps I took:
$ lein new app latinsq
I then modified project.clj as follows:
(defproject latinsq "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.8.0"]]
:main latinsq.core
:target-path "target/%s"
:profiles {:uberjar {:aot :all}})
and /latinsq/src/latinsq/core.clj
(ns latinsq.core
(:use [clojure.set :only (difference)]))
(defn replace-at
"in string s, replaces character at index p with c"
[s p c]
(str
(.substring s 0 p)
c
(.substring s (inc p))))
; memoized function to save time on sqrt calls
(def sqrt (memoize (fn [x] (Math/sqrt x))))
(defn candidates
"assuming that the position pos is empty in sq, return those values that it might be"
[pos sq]
(let [sq-size (int (sqrt (count sq)))]
; set difference between...
(difference
; ...all the possible values...
(set (map #(first (str %)) (range 1 (inc sq-size))))
; ...and the set of...
(into #{}
(concat
; ...those in the same column...
(map #(get sq %)
(range (rem pos sq-size)
(count sq)
sq-size))
; ...and those in the same row.
(map #(get sq %)
(map #(+ % (- pos (rem pos sq-size)))
(range 0 sq-size))))))))
(defn latinsq
"encode your partial-square as a string like 1--1
this fn returns a lazy sequence of all solutions"
[sq]
; Find the first empty square
(let [empty-pos (.indexOf sq "-")]
; if none, we don't need to do anything
(if (= -1 empty-pos)
(list sq)
; else make a lazy sequence of...
(lazy-seq
; ...the concatenation of all the results of...
(apply concat
; ...using "map" to recurse, filling in the empty
; square with...
(map #(latinsq (replace-at sq empty-pos %))
; ...each possible value in turn
(candidates empty-pos sq)))))))
;; So, now some examples
(time
(latinsq "123------"))
;; "Elapsed time: 0.045368 msecs"
;; ("123231312" "123312231")
(time
(latinsq "12---31--------4"))
;; "Elapsed time: 0.068511 msecs"
;; ("1243431224313124" "1243431234212134")
;; A bit harder, an empty 5x5 grid
;; has 161280 solutions according to
;; http://mathworld.wolfram.com/LatinSquare.html
(time
(count (latinsq "-------------------------")))
;; "Elapsed time: 36980.759177 msecs" <--- a bit slow
;; 161280
;; Having made sure that our function returns a lazy seq
;; the whole result can be treated lazily, so to find just one
;; solution to the 5x5 grid:
(time
(first (latinsq "-------------------------")))
;; "Elapsed time: 0.985559 msecs" <--- not slow
;; "1234521453345124523153124"
;; first 3 of 5524751496156892842531225600 solutions for a 9x9 grid
(time
(take 3 (latinsq "---------------------------------------------------------------------------------")))
;; "Elapsed time: 0.075874 msecs"
;; ("123456789214365897341278956432189675567891234658917342789523461896742513975634128"
;; "123456789214365897341278956432189675567891234658917342789523461975634128896742513"
;; "123456789214365897341278956432189675567891234658917342789524163896743521975632418")
I'm getting the following error:
Exception in thread "main" java.lang.Exception: Cannot find anything to run for: latinsq.core, compiling:(/tmp/form-init4810859530587029884.clj:1:73)
at clojure.lang.Compiler.load(Compiler.java:7391)
at clojure.lang.Compiler.loadFile(Compiler.java:7317)
at clojure.main$load_script.invokeStatic(main.clj:275)
at clojure.main$init_opt.invokeStatic(main.clj:277)
at clojure.main$init_opt.invoke(main.clj:277)
at clojure.main$initialize.invokeStatic(main.clj:308)
at clojure.main$null_opt.invokeStatic(main.clj:342)
at clojure.main$null_opt.invoke(main.clj:339)
at clojure.main$main.invokeStatic(main.clj:421)
at clojure.main$main.doInvoke(main.clj:384)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:383)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
Caused by: java.lang.Exception: Cannot find anything to run for: latinsq.core
at user$eval5.invokeStatic(form-init4810859530587029884.clj:1)
at user$eval5.invoke(form-init4810859530587029884.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6927)
at clojure.lang.Compiler.eval(Compiler.java:6917)
at clojure.lang.Compiler.load(Compiler.java:7379)
... 14 more
From the research I have done, the issue is caused by the name on :main. I've tinkered with this a few times and I have not been able to get this to work. Is this because "latinsq" is showing up too many times in the directory tree? Or, am I misunderstanding how to run the code.
Alternatively, when I finally get it to run, the only output is:
"Elapsed time: 0.468492 msecs"
"Elapsed time: 0.0796 msecs"
You forgot to define -main
function - this one is automatically generated by leiningen in core namespace.
You also didn't specify how you try to run the application, but I assume you just invoke lein run
.
As long as you add -main
function to your namespace it should work.
I also recommend wrapping the latinsq
function invocations into another function to avoid evaluating them when namespace is loaded.
Btw. this is the full output that I got (using unmodified -main
generated by leiningen:
lein run
"Elapsed time: 0.183692 msecs"
"Elapsed time: 0.055872 msecs"
"Elapsed time: 68742.261628 msecs"
"Elapsed time: 1.361745 msecs"
"Elapsed time: 0.045366 msecs"
Hello, World!