Skip to content

Commit

Permalink
awk/all-your-base: 1st iteration
Browse files Browse the repository at this point in the history
  • Loading branch information
vpayno committed Sep 22, 2023
1 parent ac1251d commit 0ad890b
Show file tree
Hide file tree
Showing 8 changed files with 427 additions and 5 deletions.
1 change: 1 addition & 0 deletions awk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@
- [scrabble-score](./scrabble-score/README.md)
- [etl](./etl/README.md)
- [space-age](./space-age/README.md)
- [all-your-base](./all-your-base/README.md)
1 change: 1 addition & 0 deletions awk/all-your-base/.lint_default_vars
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-v obase=10
9 changes: 8 additions & 1 deletion awk/all-your-base/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,11 @@ I think you got the idea!

### Created by

- @IsaacG
- @IsaacG

### My Solution

- [my solution](./all-your-base.awk)
- [awkunit tests](./all-your-base_test.awk)
- [test cases](./test-cases.awk)
- [run-tests](./run-tests-awk.txt)
114 changes: 110 additions & 4 deletions awk/all-your-base/all-your-base.awk
Original file line number Diff line number Diff line change
@@ -1,8 +1,114 @@
#!/usr/bin/gawk --bignum --lint --file

@load "ordchr"

# These variables are initialized on the command line (using '-v'):
# - ibase
# - obase
# - ibase -> uint
# - obase -> uint

function to_base_10(input_base, input_digits) {
base_ten = 0

_ = split(input_digits, digits, " ")

for (i in digits) {
# print "digit: [" digits[i] "]"

base_ten *= input_base
base_ten += digits[i]
}

# print "base_ten: [" base_ten "]"

return base_ten
}

function from_base_10(output_base, number) {
output_digits = ""

# if number isn't an int here, it will keep aproaching zero for more than a few iterations
while (number > 0) {
# print "number: [" number "]"

tmp = number % output_base
tmp = int(tmp)

if (output_digits == "") {
output_digits = tmp
} else {
output_digits = tmp " " output_digits
}

number /= output_base
number = int(number)
}

return output_digits
}

function allYourBase(input_base, output_base, input_digits) {
# print "ibase: [" input_base "]"
# print "obase: [" output_base "]"
# print "input_digits: [" input_digits "]"

if (int(input_base) <= 1) {
return "error:input base, " input_base ", is less than or equal to 1"
}

if (int(output_base) <= 1) {
return "error:output base, " output_base ", is less than or equal to 1"
}

if (length(input_digits) == 0) {
# return "error:input digits list is empty"
# the test expects no output
return ""
}

_ = split(input_digits, digits, " ")

for (i in digits) {
if (int(digits[i]) >= int(input_base)) {
return "error:found input digit, " digits[i] ", that is larger than input base, " input_base
}

if (int(digits[i]) < 0) {
return "error:found negative input digit, " digits[i]
}
}

return from_base_10(output_base, to_base_10(input_base, input_digits))
}

BEGIN {
print "Implement this solution" > "/dev/stderr"
exit 1
}

{
# let's make sure ibase isn't being used to inject code
if (! match(ibase, /^([0-9]+)$/)) {
print "error: invalid input base [" ibase "], expecting unsigned integer" #> /dev/stderr
exit 1
}

# let's make sure obase isn't being used to inject code
if (! match(obase, /^([0-9]+)$/)) {
print "error: invalid output base [" obase "], expecting unsigned integer" #> /dev/stderr
exit 1
}

result = allYourBase(ibase, obase, $0)

if (match(result, /^error:/)) {
_ = split(result, parts, ":")
level = parts[1]
message = parts[2]

print "[" level "]: " message #> /dev/stderr
exit 1
}

print result
}

END {
}
101 changes: 101 additions & 0 deletions awk/all-your-base/all-your-base_test.awk
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#!/usr/bin/gawk --bignum --lint --file

@include "awkunit"
@include "test-cases"
@include "all-your-base"

passed = 0
testCount = 0

function _debugTestPre() {
printf "Test %s:\n", (passed + 1)
printf " input -> [%s]\n", input_base
printf " digits -> [%s]\n", input_digits
}

function _debugTestPost() {
passed = passed + 1
printf " output -> [%s]\n", got
printf " result -> passed\n\n"
}

function testAllYourBase_2to10() {
input_base = "2"
output_base = "10"
input_digits = "1 0 1"
want = "5"

# _ = split(input, a, " ")

_debugTestPre()
got = allYourBase(input_base, output_base, input_digits)

assertEquals(got, want)
_debugTestPost()
}

function testAllYourBase_10to2() {
input_base = "10"
output_base = "2"
input_digits = "5"
want = "1 0 1"

# _ = split(input, a, " ")

_debugTestPre()
got = allYourBase(input_base, output_base, input_digits)

assertEquals(got, want)
_debugTestPost()
}

function casesAllYourBase() {
printf "Running %d test cases\n\n", length(cases)
caseNum = 0

# orders array by index in for loop
PROCINFO["sorted_in"] = "@ind_str_asc"

# Associative arrays don't preserve insert order.
for (key in cases) {
input = key
want = cases[key]

_ = split(input, a, ":")

input_base = a[1]
output_base = a[2]
input_digits = a[3]

_debugTestPre()
got = allYourBase(input_base, output_base, input_digits)

assertEquals(got, want)
_debugTestPost()
}
}

BEGIN {
exit 0
}

END {
cmd = "grep --no-filename --count ^function\\ test *_test.awk"
cmd | getline testCount

printf "\nRunning %d tests...\n\n", testCount

testCount = testCount + length(cases)

# running tests with a lot of duplication
testAllYourBase_2to10()
testAllYourBase_10to2()

# running tests with reduced duplication
casesAllYourBase()

print "\n" passed " out of " testCount " tests passed!"

# add exit here to keep it from looping
exit 0
}
1 change: 1 addition & 0 deletions awk/all-your-base/awkunit.awk
Loading

0 comments on commit 0ad890b

Please sign in to comment.