From 3f9241936a79c74ad68e55c445cd5504937839d0 Mon Sep 17 00:00:00 2001 From: Glenn Jackman Date: Thu, 7 Nov 2024 21:35:07 -0500 Subject: [PATCH] reimplementation to include all the tests: use string addition --- config.json | 7 +++- .../grains/.docs/instructions.append.md | 3 +- exercises/practice/grains/.meta/config.json | 3 +- exercises/practice/grains/.meta/example.vim | 38 ++++++++++++++++--- exercises/practice/grains/.meta/tests.toml | 3 -- exercises/practice/grains/grains.vader | 32 ++++++++-------- exercises/practice/grains/grains.vim | 10 ++--- 7 files changed, 64 insertions(+), 32 deletions(-) diff --git a/config.json b/config.json index 2672181..3c4f6d2 100644 --- a/config.json +++ b/config.json @@ -185,7 +185,12 @@ "uuid": "99408193-d0ce-4c68-8cab-e680f3ed56a4", "practices": [], "prerequisites": [], - "difficulty": 2 + "difficulty": 5, + "topics": [ + "math", + "strings", + "loops" + ] }, { "slug": "hello-world", diff --git a/exercises/practice/grains/.docs/instructions.append.md b/exercises/practice/grains/.docs/instructions.append.md index 0135f08..cb25238 100644 --- a/exercises/practice/grains/.docs/instructions.append.md +++ b/exercises/practice/grains/.docs/instructions.append.md @@ -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 diff --git a/exercises/practice/grains/.meta/config.json b/exercises/practice/grains/.meta/config.json index c090ed4..bbe908c 100644 --- a/exercises/practice/grains/.meta/config.json +++ b/exercises/practice/grains/.meta/config.json @@ -1,6 +1,7 @@ { "authors": [ - "BNAndras" + "BNAndras", + "glennj" ], "files": { "solution": [ diff --git a/exercises/practice/grains/.meta/example.vim b/exercises/practice/grains/.meta/example.vim index d68bac7..a6b21b4 100644 --- a/exercises/practice/grains/.meta/example.vim +++ b/exercises/practice/grains/.meta/example.vim @@ -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 diff --git a/exercises/practice/grains/.meta/tests.toml b/exercises/practice/grains/.meta/tests.toml index 64b1d37..6ea68bc 100644 --- a/exercises/practice/grains/.meta/tests.toml +++ b/exercises/practice/grains/.meta/tests.toml @@ -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" @@ -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 diff --git a/exercises/practice/grains/grains.vader b/exercises/practice/grains/grains.vader index 1cd79d0..a6b6906 100644 --- a/exercises/practice/grains/grains.vader +++ b/exercises/practice/grains/grains.vader @@ -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() diff --git a/exercises/practice/grains/grains.vim b/exercises/practice/grains/grains.vim index 859b744..c8e26cd 100644 --- a/exercises/practice/grains/grains.vim +++ b/exercises/practice/grains/grains.vim @@ -1,7 +1,7 @@ " -" 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: " @@ -9,14 +9,14 @@ " 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