Add elisp/grains
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
# Grains
|
||||||
|
|
||||||
|
Calculate the number of grains of wheat on a chessboard given that the number
|
||||||
|
on each square doubles.
|
||||||
|
|
||||||
|
There once was a wise servant who saved the life of a prince. The king
|
||||||
|
promised to pay whatever the servant could dream up. Knowing that the
|
||||||
|
king loved chess, the servant told the king he would like to have grains
|
||||||
|
of wheat. One grain on the first square of a chess board. Two grains on
|
||||||
|
the next. Four on the third, and so on.
|
||||||
|
|
||||||
|
There are 64 squares on a chessboard.
|
||||||
|
|
||||||
|
Write code that shows:
|
||||||
|
- how many grains were on each square, and
|
||||||
|
- the total number of grains
|
||||||
|
|
||||||
|
|
||||||
|
## For bonus points
|
||||||
|
|
||||||
|
Did you get the tests passing and the code clean? If you want to, these
|
||||||
|
are some additional things you could try:
|
||||||
|
|
||||||
|
- Optimize for speed.
|
||||||
|
- Optimize for readability.
|
||||||
|
|
||||||
|
Then please share your thoughts in a comment on the submission. Did this
|
||||||
|
experiment make the code better? Worse? Did you learn anything from it?
|
||||||
|
## Source
|
||||||
|
|
||||||
|
JavaRanch Cattle Drive, exercise 6 [http://www.javaranch.com/grains.jsp](http://www.javaranch.com/grains.jsp)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
;;; grains-test.el --- Test for Grains (exercism)
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(load-file "grains.el")
|
||||||
|
|
||||||
|
(ert-deftest square-1 ()
|
||||||
|
(should (= 1 (square 1))))
|
||||||
|
|
||||||
|
(ert-deftest square-2 ()
|
||||||
|
(should (= 2 (square 2))))
|
||||||
|
|
||||||
|
(ert-deftest square-3 ()
|
||||||
|
(should (= 4 (square 3))))
|
||||||
|
|
||||||
|
(ert-deftest square-4 ()
|
||||||
|
(should (= 8 (square 4))))
|
||||||
|
|
||||||
|
(ert-deftest square-16 ()
|
||||||
|
(should (= 32768
|
||||||
|
(square 16))))
|
||||||
|
|
||||||
|
(ert-deftest square-32 ()
|
||||||
|
(should (= 2147483648
|
||||||
|
(square 32))))
|
||||||
|
|
||||||
|
(ert-deftest square-64 ()
|
||||||
|
(should (= 9223372036854775808
|
||||||
|
(square 64))))
|
||||||
|
|
||||||
|
(ert-deftest total-grains ()
|
||||||
|
(should (= 18446744073709551615
|
||||||
|
(total))))
|
||||||
|
|
||||||
|
(provide 'grains-test.el)
|
||||||
|
;;; grains-test.el ends here.
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
;;; grains.el --- Grains exercise (exercism)
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;; I solved this problem on the C track. There, the solution was
|
||||||
|
;;; simpler: simply shift an unsigned long long to get the number of
|
||||||
|
;;; grains at square n.
|
||||||
|
;;;
|
||||||
|
;;; In Emacs, that approach doesn't seem to work. Only 30 bits are used
|
||||||
|
;;; for integers, resulting in overflows above square 60.
|
||||||
|
;;;
|
||||||
|
;;; The solution, if one wants to calculate it, seems to be to rely on
|
||||||
|
;;; the calc package to calculate bigger numbers. The functions
|
||||||
|
;;; calculate-square and calculate-total rely on that approach.
|
||||||
|
;;;
|
||||||
|
;;; However, it also occurred to me that the values here are known,
|
||||||
|
;;; limited, and not likely to change anytime soon. By using contants,
|
||||||
|
;;; we can get constant time determination of the number of grains for
|
||||||
|
;;; a square. The functions used by the tests, square and total, simply
|
||||||
|
;;; return constant values, with the number of grains for a square
|
||||||
|
;;; relying on a vector that matches the n-th index to the corresponding
|
||||||
|
;;; grains.
|
||||||
|
;;;
|
||||||
|
;;; Emacs itself was useful in effectuating this solution. I used a
|
||||||
|
;;; macro to evaluate calculate-square for n, and then insert the
|
||||||
|
;;; results in this buffer. There's probably a more elegant way to do
|
||||||
|
;;; this in Emacs, but this approach was adequate for the task.
|
||||||
|
;;; Sometimes, making the programmer's life easier can lead to more
|
||||||
|
;;; efficient code.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'calc)
|
||||||
|
|
||||||
|
(defun calculate-square(n)
|
||||||
|
"Return the number of grains at square N. Use left shifts when n is equal to or below 60, and calc for numbers up to 65."
|
||||||
|
(cond ((< n 0) 0)
|
||||||
|
((> n 65) 0)
|
||||||
|
((<= n 60) (lsh 1 (- n 1)))
|
||||||
|
(t (string-to-number (calc-eval (format "2^%d" (1- n)))))))
|
||||||
|
|
||||||
|
(defun calculate-total()
|
||||||
|
"Return the total number of grains on a chessboard with 64 squares."
|
||||||
|
(1- (square 65)))
|
||||||
|
|
||||||
|
(defvar grains [0
|
||||||
|
1
|
||||||
|
2
|
||||||
|
4
|
||||||
|
8
|
||||||
|
16
|
||||||
|
32
|
||||||
|
64
|
||||||
|
128
|
||||||
|
256
|
||||||
|
512
|
||||||
|
1024
|
||||||
|
2048
|
||||||
|
4096
|
||||||
|
8192
|
||||||
|
16384
|
||||||
|
32768
|
||||||
|
65536
|
||||||
|
131072
|
||||||
|
262144
|
||||||
|
524288
|
||||||
|
1048576
|
||||||
|
2097152
|
||||||
|
4194304
|
||||||
|
8388608
|
||||||
|
16777216
|
||||||
|
33554432
|
||||||
|
67108864
|
||||||
|
134217728
|
||||||
|
268435456
|
||||||
|
536870912
|
||||||
|
1073741824
|
||||||
|
2147483648
|
||||||
|
4294967296
|
||||||
|
8589934592
|
||||||
|
17179869184
|
||||||
|
34359738368
|
||||||
|
68719476736
|
||||||
|
137438953472
|
||||||
|
274877906944
|
||||||
|
549755813888
|
||||||
|
1099511627776
|
||||||
|
2199023255552
|
||||||
|
4398046511104
|
||||||
|
8796093022208
|
||||||
|
17592186044416
|
||||||
|
35184372088832
|
||||||
|
70368744177664
|
||||||
|
140737488355328
|
||||||
|
281474976710656
|
||||||
|
562949953421312
|
||||||
|
1125899906842624
|
||||||
|
2251799813685248
|
||||||
|
4503599627370496
|
||||||
|
9007199254740992
|
||||||
|
18014398509481984
|
||||||
|
36028797018963968
|
||||||
|
72057594037927936
|
||||||
|
144115188075855872
|
||||||
|
288230376151711744
|
||||||
|
576460752303423488
|
||||||
|
1152921504606846976
|
||||||
|
2305843009213693952
|
||||||
|
4611686018427387904
|
||||||
|
9223372036854775808]
|
||||||
|
"Vector containing the number of grains for a square with the corresponding index.")
|
||||||
|
|
||||||
|
(defun square(n)
|
||||||
|
"Return the number of grans at square n; 0 for negative numbers and numbers above 64."
|
||||||
|
(cond ((< n 0) 0)
|
||||||
|
((> n 64) 0)
|
||||||
|
(t (aref grains n))))
|
||||||
|
|
||||||
|
(defun total()
|
||||||
|
"Return the total number of grains on a chessboard with 64 squares."
|
||||||
|
18446744073709551616)
|
||||||
|
|
||||||
|
(provide 'grains)
|
||||||
|
;;; grains.el ends here
|
||||||
Reference in New Issue
Block a user