Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change the max square for grains #322

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,12 @@
"uuid": "99408193-d0ce-4c68-8cab-e680f3ed56a4",
"practices": [],
"prerequisites": [],
"difficulty": 2,
"status": "wip"
"difficulty": 5,
"topics": [
"math",
"strings",
"loops"
]
},
{
"slug": "hello-world",
Expand Down
12 changes: 12 additions & 0 deletions exercises/practice/grains/.docs/instructions.append.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## Maximum integer value

According to [the Vim docs][number]:

> Assuming 64 bit numbers are used (see v:numbersize) an unsigned number is truncated to 0x7fffffffffffffff or 9223372036854775807.

That means that Vim cannot express any number `2^63` or greater as an integer.

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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not crazy about this line. Addition is not the only way to do this, so we will not have to necessarily do this, but it states that we will have to do so. The word "implement", with its definitions, is ambiguous, and it may the solution does not use (at least only) two operands of any kind.

Also, the exercise will have us return the values as strings, but that does not mean what the line after says it means.

Perhaps part of my angst here is the "that means" part that is stated 4 lines above as well.

How can we phrase this so that the restrictions in Vimscript is stated, but the solution is left to the exerciser to be thought and explored.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other words, Vimscript cannot express any number `2^63` or greater as an integer.

Some of the tests for this exercise require 64 bit integers and thus cannot be solved using only integer arithmetic.
The tests have been written to expect the return values as strings.
How can you implement arithmetic operations that return strings?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can you implement arithmetic operations that return strings?

Maybe:

"Can you solve this by avoiding numbers that are larger than the language will allow directly?"

The tests will inform that the returns must be strings, and if the tests change later, then we do not have to change that aspect. The communication is (hopefully) clear.

and thus cannot be solved using only integer arithmetic.

"which is beyond the integer size limitation of Vimscript."

The tests have been written to expect the return values as strings.

"Because of the language limitations regarding integers, the results of the calculations are tested against a string which expresses the integer value, rather than expressing the answer as Integer."

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, notice that I do avoid the use of "implement" as the word has confusing definitions. "The implement implements an implementation, within another implement." This statement is clear, but unless you are a native English speaker, it is may be hard to follow.


[number]: https://vimhelp.org/eval.txt.html#expr-number
4 changes: 3 additions & 1 deletion exercises/practice/grains/.meta/config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"authors": [
"BNAndras"
"BNAndras",
"KOTP",
"glennj"
],
"files": {
"solution": [
Expand Down
62 changes: 55 additions & 7 deletions exercises/practice/grains/.meta/example.vim
Original file line number Diff line number Diff line change
@@ -1,11 +1,59 @@
function! Square(number) abort
if a:number < 1 || a:number > 64
throw 'square must be between 1 and 64'
endif
" Helper function to add two large numbers represented as strings
function! StringAdd(num1, num2)
let carry = 0
let result = ''

return float2nr(pow(2, (a:number-1)))
" Pad the shorter number with leading zeros
let len1 = strlen(a:num1)
let len2 = strlen(a:num2)
if len1 < len2
let a:num1 = repeat('0', len2 - len1) . a:num1
elseif len2 < len1
let a:num2 = repeat('0', len1 - len2) . a:num2
endif

" Add digits from right to left
for i in range(strlen(a:num1) - 1, 0, -1)
let sum = str2nr(a:num1[i]) + str2nr(a:num2[i]) + carry
let carry = sum >= 10 ? 1 : 0
let result = string(sum % 10) . result
endfor

" Add the last carry if it exists
if carry > 0
let result = '1' . result
endif

return result
endfunction

function! Total() abort
return float2nr(pow(2, 64) - 1)
" Function to calculate grains on a specific square using string manipulation
function! Square(n)
if a:n < 1 || a:n > 64
throw 'square must be between 1 and 64'
endif

" Start with 1 grain on the first square
let grains = '1'
for i in range(2, a:n)
" Double the grains by adding it to itself
let grains = StringAdd(grains, grains)
endfor

return grains
endfunction

" Function to calculate the total grains on the chessboard using string manipulation
function! Total()
let total = '0'

" Accumulate grains for each square from 1 to 64
let grains = '1'
for i in range(1, 64)
let total = StringAdd(total, grains)
" Double grains for the next square
let grains = StringAdd(grains, grains)
endfor

return total
endfunction
16 changes: 8 additions & 8 deletions exercises/practice/grains/grains.vader
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@

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 64):
let g:square = 64
let g:expected = 9223372036854775807
let g:expected = "9223372036854775808"
AssertEqual g:expected, Square(g:square)

Execute (square 0 is invalid):
Expand All @@ -53,5 +53,5 @@ Execute (square greater than 64 is invalid):
AssertEqual g:expected, g:vader_exception

Execute (returns the total number of grains on the board):
let g:expected = 9223372036854775807
let g:expected = "18446744073709551615"
AssertEqual g:expected, Total()
6 changes: 3 additions & 3 deletions exercises/practice/grains/grains.vim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"
" Returns the number of grains on a chessboard square given the grains on each square
" double from the previous square.
" 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:
Expand All @@ -16,7 +16,7 @@ function! Square(number) abort
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