Skip to content

Commit

Permalink
reimplementation to include all the tests: use string addition
Browse files Browse the repository at this point in the history
  • Loading branch information
glennj committed Nov 8, 2024
1 parent 811b20d commit 3f92419
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 32 deletions.
7 changes: 6 additions & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,12 @@
"uuid": "99408193-d0ce-4c68-8cab-e680f3ed56a4",
"practices": [],
"prerequisites": [],
"difficulty": 2
"difficulty": 5,
"topics": [
"math",
"strings",
"loops"
]
},
{
"slug": "hello-world",
Expand Down
3 changes: 2 additions & 1 deletion exercises/practice/grains/.docs/instructions.append.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ According to [the Vim docs][number]:
That means that Vim cannot express any number `2^63` or greater as an integer.

For the purposes of this exercise, we will declare that in Vimland, chess boards are 7x7 and have **49** squares.
For this exercise, you will return the values as strings.
That means you will have to implement a way to do addition on two _string_ operands.

[number]: https://vimhelp.org/eval.txt.html#expr-number
3 changes: 2 additions & 1 deletion exercises/practice/grains/.meta/config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"authors": [
"BNAndras"
"BNAndras",
"glennj"
],
"files": {
"solution": [
Expand Down
38 changes: 33 additions & 5 deletions exercises/practice/grains/.meta/example.vim
Original file line number Diff line number Diff line change
@@ -1,11 +1,39 @@
" add two strings as numbers from right to left, as if by hand
function! StringAdd(a, b) abort
" zero-left-pad so the numbers are the same length
let len = [a:a->strlen(), a:b->strlen()]->max()
let a = printf('%0*s', len, a:a)
let b = printf('%0*s', len, a:b)
let result = ""
let carry = 0

for i in range(len - 1, 0, -1)
let c = carry + a->strpart(i, 1)->str2nr() + b->strpart(i, 1)->str2nr()
let result = $"{c % 10}{result}"
let carry = c / 10
endfor
return $"{carry}{result}"->trim('0', 1)
endfunction

" populate the squares, doubling each previous, cache in the script scope
let s:grains = ['1']
for i in range(1, 63)
eval s:grains->add(StringAdd(s:grains[i - 1], s:grains[i - 1]))
endfor

" return the grains on square `number`
function! Square(number) abort
if a:number < 1 || a:number > 49
throw 'square must be between 1 and 49'
if a:number < 1 || a:number > 64
throw 'square must be between 1 and 64'
endif

return float2nr(pow(2, (a:number-1)))
return s:grains[a:number - 1]
endfunction

" return the total number of grains
function! Total() abort
return float2nr(pow(2, 49) - 1)
let total = '0'
for i in range(64)
let total = StringAdd(total, s:grains[i])
endfor
return total
endfunction
3 changes: 0 additions & 3 deletions exercises/practice/grains/.meta/tests.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ description = "returns the number of grains on the square -> grains on square 32

[c73b470a-5efb-4d53-9ac6-c5f6487f227b]
description = "returns the number of grains on the square -> grains on square 64"
include = false

[1d47d832-3e85-4974-9466-5bd35af484e3]
description = "returns the number of grains on the square -> square 0 is invalid"
Expand All @@ -39,8 +38,6 @@ description = "returns the number of grains on the square -> negative square is

[a95e4374-f32c-45a7-a10d-ffec475c012f]
description = "returns the number of grains on the square -> square greater than 64 is invalid"
include = false

[6eb07385-3659-4b45-a6be-9dc474222750]
description = "returns the total number of grains on the board"
include = false
32 changes: 16 additions & 16 deletions exercises/practice/grains/grains.vader
Original file line number Diff line number Diff line change
@@ -1,57 +1,57 @@

Execute (grains on square 1):
let g:square = 1
let g:expected = 1
let g:expected = "1"
AssertEqual g:expected, Square(g:square)

Execute (grains on square 2):
let g:square = 2
let g:expected = 2
let g:expected = "2"
AssertEqual g:expected, Square(g:square)

Execute (grains on square 3):
let g:square = 3
let g:expected = 4
let g:expected = "4"
AssertEqual g:expected, Square(g:square)

Execute (grains on square 4):
let g:square = 4
let g:expected = 8
let g:expected = "8"
AssertEqual g:expected, Square(g:square)

Execute (grains on square 16):
let g:square = 16
let g:expected = 32768
let g:expected = "32768"
AssertEqual g:expected, Square(g:square)

Execute (grains on square 32):
let g:square = 32
let g:expected = 2147483648
let g:expected = "2147483648"
AssertEqual g:expected, Square(g:square)

Execute (grains on square 49):
let g:square = 49
let g:expected = 281474976710656
Execute (grains on square 64):
let g:square = 64
let g:expected = "9223372036854775808"
AssertEqual g:expected, Square(g:square)

Execute (square 0 is invalid):
let g:square = 0
let g:expected = "square must be between 1 and 49"
let g:expected = "square must be between 1 and 64"
AssertThrows call Square(g:square)
AssertEqual g:expected, g:vader_exception

Execute (negative square is invalid):
let g:square = -1
let g:expected = "square must be between 1 and 49"
let g:expected = "square must be between 1 and 64"
AssertThrows call Square(g:square)
AssertEqual g:expected, g:vader_exception

Execute (square greater than 49 is invalid):
let g:square = 50
let g:expected = "square must be between 1 and 49"
Execute (square greater than 64 is invalid):
let g:square = 65
let g:expected = "square must be between 1 and 64"
AssertThrows call Square(g:square)
AssertEqual g:expected, g:vader_exception

Execute (returns the total number of grains on the board for 49 squares):
let g:expected = 562949953421311
Execute (returns the total number of grains on the board):
let g:expected = "18446744073709551615"
AssertEqual g:expected, Total()
10 changes: 5 additions & 5 deletions exercises/practice/grains/grains.vim
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
"
" Returns the number of grains on a chessboard square given the grains on each square
" double from the previous square.
" Throws an error if the square is below 1 or above 49.
" Returns the number of grains (as a string) on a chessboard square given the
" grains on each square double from the previous square.
" Throws an error if the square is below 1 or above 64.
"
" Examples:
"
" :echo Square(16)
" 32768
"
" :echo Square(-1)
" E605: Exception not caught: square must be between 1 and 49
" E605: Exception not caught: square must be between 1 and 64
"
function! Square(number) abort
" your code goes here
endfunction

"
" Returns the total number of grains for a filled chessboard
" Returns the total number of grains (as a string) for a filled chessboard
"
function! Total() abort
" your code goes here
Expand Down

0 comments on commit 3f92419

Please sign in to comment.