Skip to content
This repository has been archived by the owner on Aug 21, 2023. It is now read-only.

feat(exercise): add exercise register03 #188

Merged
merged 3 commits into from
Jun 13, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
94 changes: 16 additions & 78 deletions .patches/registers/registers02.cairo.patch
Original file line number Diff line number Diff line change
@@ -1,78 +1,16 @@
--- exercises/registers/registers02.cairo 2022-05-18 12:53:44.000000000 -0400
+++ .tmp_solution/registers02.cairo 2022-05-18 11:40:22.000000000 -0400
@@ -3,0 +4 @@
+
@@ -9,6 +10,2 @@
-func sum_array(array_len : felt, array : felt*) -> (sum : felt):
- # [ap] = [fp - 4]; ap++
- # [ap] = [fp - 3]; ap++
- # [ap] = 0; ap++
- # call rec_sum_array
- # ret
+func sum_array(array_len: felt, array: felt*) -> (sum: felt):
+ return rec_sum_array(array_len, array, 0)
@@ -17,16 +14,6 @@
-func rec_sum_array(array_len : felt, array : felt*, sum : felt) -> (sum : felt):
- # jmp continue if [fp - 5] != 0
-
- # stop:
- # [ap] = [fp - 3]; ap++
- # jmp done
-
- # continue:
- # [ap] = [[fp - 4]]; ap++
- # [ap] = [fp - 5] - 1; ap++
- # [ap] = [fp - 4] + 1; ap++
- # [ap] = [ap - 3] + [fp - 3]; ap++
- # call rec_sum_array
-
- # done:
- # ret
+func rec_sum_array(array_len: felt, array: felt*, sum: felt) -> (sum: felt):
+ if array_len == 0:
+ return (sum)
+ end
+
+ return rec_sum_array(array_len - 1, array + 1, sum + array[0])
@@ -39,7 +26,31 @@
-func max{range_check_ptr}(a : felt, b : felt) -> (max : felt):
- # let (res) = is_le(a, b)
- # if res == 1:
- # return (b)
- # else:
- # return (a)
- # end
+func max{range_check_ptr}(a: felt, b: felt) -> (max: felt):
+ # Push arguments to the stack
+ [ap] = [fp - 5]; ap++ # range_check_ptr
+ [ap] = [fp - 4]; ap++ # a
+ [ap] = [fp - 3]; ap++ # b
+
+ # This call will return two values
+ # 1) the updated range_check_ptr
+ # 2) 0 or 1 depending on which of a and b is greater
+ call is_le
+
+ # Push return values to the stack
+ # There is two of them to push: range_check_ptr and max
+
+ # Push the first one, the updated range_check_ptr, onto the stack
+ [ap] = [ap - 2]; ap++
+
+ # Conditional jump
+ # The following blocks are an assembly level equivalent of the if/else pattern
+ jmp b_is_more if [ap - 2] !=0 # here [ap-2] is the second value returned by is_le, our boolean
+
+ # Push either a or b to the stack
+ a_is_more:
+ [ap] = [fp - 4]; ap++
+ jmp done
+
+ b_is_more:
+ [ap] = [fp -3]; ap++
+
+ done:
+ ret
@@ -79 +90 @@
-
+
--- exercises/registers/registers02.cairo 2022-06-11 22:20:43.000000000 -0400
+++ ./registers02.cairo 2022-06-11 22:18:21.000000000 -0400
@@ -17,3 +17,3 @@
- # [ap] = 42; ap++
- # [ap - 1] = 42
- # [ap - 1] = 21
+ tempvar x = 42
+ assert x = 42
+ assert x = 21
@@ -27 +27 @@
- # assert number = 42
+ [fp -3] = 42
@@ -37,0 +38 @@
+ assert [p_number] = 42
@@ -45,0 +47 @@
+ assert 42 = [p_number]
78 changes: 78 additions & 0 deletions .patches/registers/registers03.cairo.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
--- exercises/registers/registers03.cairo 2022-05-18 12:53:44.000000000 -0400
+++ .tmp_solution/registers03.cairo 2022-05-18 11:40:22.000000000 -0400
@@ -3,0 +4 @@
+
@@ -9,6 +10,2 @@
-func sum_array(array_len : felt, array : felt*) -> (sum : felt):
- # [ap] = [fp - 4]; ap++
- # [ap] = [fp - 3]; ap++
- # [ap] = 0; ap++
- # call rec_sum_array
- # ret
+func sum_array(array_len: felt, array: felt*) -> (sum: felt):
+ return rec_sum_array(array_len, array, 0)
@@ -17,16 +14,6 @@
-func rec_sum_array(array_len : felt, array : felt*, sum : felt) -> (sum : felt):
- # jmp continue if [fp - 5] != 0
-
- # stop:
- # [ap] = [fp - 3]; ap++
- # jmp done
-
- # continue:
- # [ap] = [[fp - 4]]; ap++
- # [ap] = [fp - 5] - 1; ap++
- # [ap] = [fp - 4] + 1; ap++
- # [ap] = [ap - 3] + [fp - 3]; ap++
- # call rec_sum_array
-
- # done:
- # ret
+func rec_sum_array(array_len: felt, array: felt*, sum: felt) -> (sum: felt):
+ if array_len == 0:
+ return (sum)
+ end
+
+ return rec_sum_array(array_len - 1, array + 1, sum + array[0])
@@ -39,7 +26,31 @@
-func max{range_check_ptr}(a : felt, b : felt) -> (max : felt):
- # let (res) = is_le(a, b)
- # if res == 1:
- # return (b)
- # else:
- # return (a)
- # end
+func max{range_check_ptr}(a: felt, b: felt) -> (max: felt):
+ # Push arguments to the stack
+ [ap] = [fp - 5]; ap++ # range_check_ptr
+ [ap] = [fp - 4]; ap++ # a
+ [ap] = [fp - 3]; ap++ # b
+
+ # This call will return two values
+ # 1) the updated range_check_ptr
+ # 2) 0 or 1 depending on which of a and b is greater
+ call is_le
+
+ # Push return values to the stack
+ # There is two of them to push: range_check_ptr and max
+
+ # Push the first one, the updated range_check_ptr, onto the stack
+ [ap] = [ap - 2]; ap++
+
+ # Conditional jump
+ # The following blocks are an assembly level equivalent of the if/else pattern
+ jmp b_is_more if [ap - 2] !=0 # here [ap-2] is the second value returned by is_le, our boolean
+
+ # Push either a or b to the stack
+ a_is_more:
+ [ap] = [fp - 4]; ap++
+ jmp done
+
+ b_is_more:
+ [ap] = [fp -3]; ap++
+
+ done:
+ ret
@@ -79 +90 @@
-
+
156 changes: 103 additions & 53 deletions exercises/registers/registers02.cairo
Original file line number Diff line number Diff line change
@@ -1,48 +1,46 @@
%lang starknet
from starkware.cairo.common.math_cmp import is_le

# I AM NOT DONE

# Cairo memory is immutable.
# Once a memory cell has been assigned, its value CANNOT be changed.
# The program will crash if someone tries to assign a new, different, value to an already initialized memory cell.
# However, trying to assign a memory cell twice, or more, **with the same value** won't cause any harm.
# This property can be used to assert the value of a cell.

# TODO
# Rewrite those functions with a high level syntax
@external
func sum_array(array_len : felt, array : felt*) -> (sum : felt):
# [ap] = [fp - 4]; ap++
# [ap] = [fp - 3]; ap++
# [ap] = 0; ap++
# call rec_sum_array
# ret
end
# Rewrite this function in a high level syntax, using tempvar and assert
func crash():
# [ap] = 42; ap++
# [ap - 1] = 42
# [ap - 1] = 21

func rec_sum_array(array_len : felt, array : felt*, sum : felt) -> (sum : felt):
# jmp continue if [fp - 5] != 0
ret
end

# stop:
# [ap] = [fp - 3]; ap++
# jmp done
# TODO
# Rewrite this funtion in a low level syntax
func assert_42(number : felt):
# assert number = 42

# continue:
# [ap] = [[fp - 4]]; ap++
# [ap] = [fp - 5] - 1; ap++
# [ap] = [fp - 4] + 1; ap++
# [ap] = [ap - 3] + [fp - 3]; ap++
# call rec_sum_array
return ()
end

# done:
# ret
# TODO
# Write this function body so:
# if the memory cell pointed by `p_number` is not initialized, set it to 42
# else, if the value is initialized and different from 42, crash
# else, do nothing and return
func assert_pointer_42(p_number : felt*):
return ()
end

# TODO
# Rewrite this function with a low level syntax
# It's possible to do it with only registers, labels and conditional jump. No reference or localvar
@external
func max{range_check_ptr}(a : felt, b : felt) -> (max : felt):
# let (res) = is_le(a, b)
# if res == 1:
# return (b)
# else:
# return (a)
# end
# Write this function body so:
# if the memory cell pointed by `p_number` is set to 42, do nothing and return
# else crash
func assert_pointer_42_no_set(p_number : felt*):
return ()
end

#########
Expand All @@ -52,30 +50,82 @@ end
from starkware.cairo.common.alloc import alloc

@external
func test_max{range_check_ptr}():
let (m) = max(21, 42)
assert m = 42
let (m) = max(42, 21)
assert m = 42
func test_crash():
%{ expect_revert() %}
crash()

return ()
end

@external
func test_sum():
let (array) = alloc()
assert array[0] = 1
assert array[1] = 2
assert array[2] = 3
assert array[3] = 4
assert array[4] = 5
assert array[5] = 6
assert array[6] = 7
assert array[7] = 8
assert array[8] = 9
assert array[9] = 10

let (s) = sum_array(10, array)
assert s = 55
func test_assert_42():
assert_42(42)

%{ expect_revert() %}
assert_42(21)

return ()
end

@external
func test_assert_pointer_42_initialized():
let (mem_zone : felt*) = alloc()
assert mem_zone[0] = 42
assert mem_zone[1] = 21

assert_pointer_42(mem_zone)

%{ expect_revert() %}
assert_pointer_42(mem_zone + 1)

return ()
end

@external
func test_assert_pointer_42_not_initialized_ok():
let (mem_zone : felt*) = alloc()
assert mem_zone[0] = 42
assert_pointer_42(mem_zone)

assert_pointer_42(mem_zone + 1)
assert mem_zone[1] = 42

return ()
end

@external
func test_assert_pointer_42_not_initialized_revert():
let (mem_zone : felt*) = alloc()
assert mem_zone[0] = 42
assert_pointer_42(mem_zone)

assert_pointer_42(mem_zone + 1)
%{ expect_revert() %}
assert mem_zone[1] = 21

return ()
end

@external
func test_assert_pointer_42_no_set():
let (mem_zone : felt*) = alloc()
assert mem_zone[0] = 42
assert mem_zone[1] = 21

assert_pointer_42_no_set(mem_zone)

%{ expect_revert() %}
assert_pointer_42_no_set(mem_zone + 1)

return ()
end

@external
func test_assert_pointer_42_no_set_crash():
let (mem_zone : felt*) = alloc()

%{ expect_revert() %}
assert_pointer_42_no_set(mem_zone)

return ()
end
Loading