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

Added new practice exercises #42

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
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
45 changes: 45 additions & 0 deletions exercises/practice/armstrong-numbers/armstrong_numbers.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package armstrong_numbers

to_digits :: proc(n: u128) -> [dynamic]u8 {
ret := make([dynamic]u8)
k := n
for k > 0 {
append(&ret, u8(k % 10))
k /= 10
}
return ret
}

fast_pow :: proc(base: u8, exp: int) -> u128 {
if exp == 0 {
return 1
}
if base < 2 {
return u128(base)
}
ret := u128(1)
a := u128(base)
n := exp
for {
if n % 2 == 1 {
ret *= a
}
n >>= 1
if n == 0 {
break
}
a *= a
}
return ret
}

is_armstrong_number :: proc(n: u128) -> bool {
digits := to_digits(n)
defer delete(digits)
power := len(digits)
sum: u128 = 0
for d in digits {
sum += fast_pow(d, power)
}
return sum == n
}
99 changes: 99 additions & 0 deletions exercises/practice/armstrong-numbers/armstrong_numbers_test.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package armstrong_numbers
import "core:testing"

@(test)
test_zero :: proc(t: ^testing.T) {
testing.expect(t, is_armstrong_number(0), "zero is an armstrong number")
}

@(test)
test_single_digit :: proc(t: ^testing.T) {
testing.expect(t, is_armstrong_number(5), "single-digit numbers are armstrong numbers")
}

@(test)
test_two_digit :: proc(t: ^testing.T) {
testing.expect(t, !is_armstrong_number(10), "there are no two-digit armstrong numbers")
}

@(test)
test_three_digit_armstrong :: proc(t: ^testing.T) {
testing.expect(t, is_armstrong_number(153), "three-digit number that is an armstrong number")
}

@(test)
test_three_digit_non_armstrong :: proc(t: ^testing.T) {
testing.expect(
t,
!is_armstrong_number(100),
"three-digit number that is not an armstrong number",
)
}

@(test)
test_four_digit_armstrong :: proc(t: ^testing.T) {
testing.expect(t, is_armstrong_number(9_474), "four-digit number that is an armstrong number")
}

@(test)
test_four_digit_non_armstrong :: proc(t: ^testing.T) {
testing.expect(
t,
!is_armstrong_number(9_475),
"four-digit number that is not an armstrong number",
)
}

@(test)
test_seven_digit_armstrong :: proc(t: ^testing.T) {
testing.expect(
t,
is_armstrong_number(9_926_315),
"seven-digit number that is an armstrong number",
)
}

@(test)
test_seven_digit_non_armstrong :: proc(t: ^testing.T) {
testing.expect(
t,
!is_armstrong_number(9_926_314),
"seven-digit number that is not an armstrong number",
)
}

@(test)
test_33_digit_armstrong :: proc(t: ^testing.T) {
testing.expect(
t,
is_armstrong_number(186_709_961_001_538_790_100_634_132_976_990),
"33-digit number that is an armstrong number",
)
}

@(test)
test_38_digit_non_armstrong :: proc(t: ^testing.T) {
testing.expect(
t,
!is_armstrong_number(99_999_999_999_999_999_999_999_999_999_999_999_999),
"38-digit number that is not an armstrong number",
)
}

@(test)
test_largest_armstrong :: proc(t: ^testing.T) {
testing.expect(
t,
is_armstrong_number(115_132_219_018_763_992_565_095_597_973_971_522_401),
"the largest and last armstrong number",
)
}

@(test)
test_largest_u128 :: proc(t: ^testing.T) {
testing.expect(
t,
!is_armstrong_number(340_282_366_920_938_463_463_374_607_431_768_211_455),
"the largest 128-bit unsigned integer value is not an armstrong number",
)
}
93 changes: 93 additions & 0 deletions exercises/practice/food-chain/food_chain.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package food_chain

import "core:strings"

Animal :: struct {
name: string,
name_long: Maybe(string),
phrase: string,
next: Maybe(^Animal),
}

fly := Animal {
name = "fly",
phrase = "I don't know why she swallowed the fly. Perhaps she'll die.",
}
spider := Animal {
name = "spider",
name_long = "spider that wriggled and jiggled and tickled inside her",
phrase = "It wriggled and jiggled and tickled inside her.",
next = &fly,
}
bird := Animal {
name = "bird",
phrase = "How absurd to swallow a bird!",
next = &spider,
}
cat := Animal {
name = "cat",
phrase = "Imagine that, to swallow a cat!",
next = &bird,
}
dog := Animal {
name = "dog",
phrase = "What a hog, to swallow a dog!",
next = &cat,
}
goat := Animal {
name = "goat",
phrase = "Just opened her throat and swallowed a goat!",
next = &dog,
}
cow := Animal {
name = "cow",
phrase = "I don't know how she swallowed a cow!",
next = &goat,
}
horse := Animal {
name = "horse",
phrase = "She's dead, of course!",
}

verses := [8]Animal{fly, spider, bird, cat, dog, goat, cow, horse}

generate_verse :: proc(builder: ^strings.Builder, i: int) {
animal: Maybe(^Animal) = &verses[i]
node, ok := animal.?
if !ok {
return
}
strings.write_string(builder, "I know an old lady who swallowed a ")
strings.write_string(builder, node.name)
strings.write_string(builder, ".\n")
if node.next != nil {
strings.write_string(builder, node.phrase)
strings.write_rune(builder, '\n')
}
for {
node := animal.? or_break
if node.next == nil {
strings.write_string(builder, node.phrase)
strings.write_rune(builder, '\n')
} else {
next := node.next.?
strings.write_string(builder, "She swallowed the ")
strings.write_string(builder, node.name)
strings.write_string(builder, " to catch the ")
name := next.name_long.? or_else next.name
strings.write_string(builder, name)
strings.write_string(builder, ".\n")
}
animal = node.next
}
}

recite :: proc(start, end: int) -> string {
builder := strings.builder_make()
defer strings.builder_destroy(&builder)
for i in start - 1 ..< end {
generate_verse(&builder, i)
strings.write_rune(&builder, '\n')
}
return strings.trim_right_space(strings.to_string(builder))
}
Loading