exercism / awk

Exercism exercises in AWK.
https://exercism.org/tracks/awk
MIT License
18 stars 21 forks source link

Building a training set of tags for awk #224

Closed iHiD closed 9 months ago

iHiD commented 10 months ago

Hello lovely maintainers :wave:

We've recently added "tags" to student's solutions. These express the constructs, paradigms and techniques that a solution uses. We are going to be using these tags for lots of things including filtering, pointing a student to alternative approaches, and much more.

In order to do this, we've built out a full AST-based tagger in C#, which has allowed us to do things like detect recursion or bit shifting. We've set things up so other tracks can do the same for their languages, but its a lot of work, and we've determined that actually it may be unnecessary. Instead we think that we can use machine learning to achieve tagging with good enough results. We've fine-tuned a model that can determine the correct tags for C# from the examples with a high success rate. It's also doing reasonably well in an untrained state for other languages. We think that with only a few examples per language, we can potentially get some quite good results, and that we can then refine things further as we go.

I released a new video on the Insiders page that talks through this in more detail.

We're going to be adding a fully-fledged UI in the coming weeks that allow maintainers and mentors to tag solutions and create training sets for the neural networks, but to start with, we're hoping you would be willing to manually tag 20 solutions for this track. In this post we'll add 20 comments, each with a student's solution, and the tags our model has generated. Your mission (should you choose to accept it) is to edit the tags on each issue, removing any incorrect ones, and add any that are missing. In order to build one model that performs well across languages, it's best if you stick as closely as possible to the C# tags as you can. Those are listed here. If you want to add extra tags, that's totally fine, but please don't arbitrarily reword existing tags, even if you don't like what Erik's chosen, as it'll just make it less likely that your language gets the correct tags assigned by the neural network.


To summarise - there are two paths forward for this issue:

  1. You're up for helping: Add a comment saying you're up for helping. Update the tags some time in the next few days. Add a comment when you're done. We'll then add them to our training set and move forward.
  2. You not up for helping: No problem! Just please add a comment letting us know :)

If you tell us you're not able/wanting to help or there's no comment added, we'll automatically crowd-source this in a week or so.

Finally, if you have questions or want to discuss things, it would be best done on the forum, so the knowledge can be shared across all maintainers in all tracks.

Thanks for your help! :blue_heart:


Note: Meta discussion on the forum

iHiD commented 10 months ago

Exercise: hamming

Code

#!/usr/bin/env gawk -f

NR == 1 { len1 = split($0, dna1, "") }
NR == 2 {
  len2 = split($0, dna2, "")
  if (len1 != len2) {
    printf("strands must be of equal length")
    exit 1
  }

  cnt = 0
  for (i=1; i<=len1; i++)
    cnt += (dna1[i] != dna2[i])
  print cnt
}

Tags:

construct:assignment
construct:for-loop
construct:if
construct:indexed-access
construct:invocation
construct:loop
construct:number
construct:parameter
construct:print
construct:printf
construct:string
construct:variable
paradigm:imperative
technique:looping
construct:add
construct:number
construct:int
iHiD commented 10 months ago

Exercise: matching-brackets

Code

#!/usr/bin/env gawk -f
#
BEGIN {
    FS = ""
    dict["]"] = "["
    dict[")"] = "("
    dict["}"] = "{"
}

{
    for (i = 1; i <= NF; ++i) {
        if ($i ~ /[({[]/) {
            stack[size++] = $i
        } else if ($i ~ /[])}]/) {
            if (stack[size - 1] == dict[$i]) {
                del stack[--size]
            } else {
                print "false"
                exit
            }
        }
    }
    print !size ? "true" : "false"
}

Tags:

construct:assignment
construct:boolean
construct:comment
construct:computed-string
construct:dictionary
construct:else
construct:exit
construct:for-loop
construct:if
construct:index
construct:indexed-access
construct:logical-not
construct:number
construct:print
construct:string
construct:subtract
construct:ternary
construct:variable
paradigm:imperative
technique:boolean-logic
technique:looping
uses:Dictionary
iHiD commented 10 months ago

Exercise: wordy

Code

function operate(op1, op2, sign){
    switch (sign){
        case "multiplied":
            return (op1 * op2)
        case "divided":
            return (op1 / op2)
        case "plus":
            return (op1 + op2)
        case "minus": 
            return (op1 - op2)                
    }
}
(! /^What is -?[[:digit:]]+( (plus|minus|divided by|multiplied by) -?[[:digit:]]+)*\?$/) {
    if ($0 ~ /[^What is|[:blank:]|\?|plus|minus|divided by|multiplied by|[:digit:]]/)
        print "unknown operation"
    else
        print "syntax error"
    exit 1
}
{
    operator[++operator_idx] = "plus"
    res = 0
    for (i = 3; i <= NF; ++i) {
        if ((!shift ? i % 2 : !(i % 2))){
                if (i == NF) 
                    number[++number_idx] = substr($i, 0, length($i) - 1)
                else
                    number[++number_idx] = $i
            }
        else {
            operator[++operator_idx] = $i
            if ($i ~ /multiplied|divided/){  
                ++i
                shift = shift ? 0 : 1
            }
        }
    }
    for (i in operator)
        res = operate(res, number[++idx], operator[i])
    print res
}

Tags:

construct:assignment
construct:boolean
construct:case
construct:divide
construct:exit
construct:for-loop
construct:function
construct:if
construct:implicit-conversion
construct:index
construct:indexed-access
construct:invocation
construct:logical-and
construct:method
construct:multiply
construct:number
construct:parameter
construct:pattern
construct:print
construct:return
construct:string
construct:subtract
construct:switch
construct:ternary
construct:variable
paradigm:imperative
technique:boolean-logic
technique:looping
technique:regular-expression
construct:add
construct:number
construct:int
iHiD commented 10 months ago

Exercise: rectangles

Code

#!/usr/bin/env gawk -f

BEGIN { FS = "" }

{
    # Record all edges/corners.
    for (i = 1; i <= NF; i++) {
        if ($i == "+")
            corner[NR][i] = 1
        if ($i == "+" || $i == "|")
            vert[NR][i] = 1
        if ($i == "+" || $i == "-")
            horiz[NR][i] = 1
    }
}

END {
    count = 0
    # Check rectangles by corners.
    for (y1 in corner) for (x1 in corner[y1]) for (y2 in corner) for (x2 in corner[y2]) {
        # Convert str to int.
        y1 = y1 + 0; y2 = y2 + 0; x1 = x1 + 0; x2 = x2 + 0
        # if (x1 == 8 && y1 == 3) printf("(%d, %d) x (%d, %d)\n", x1, y1, x2, y2)
        if (x1 >= x2 || y1 >= y2)
            continue
        if (!corner[y1][x2] || !corner[y2][x1])
            continue
        matches = 1
        for (y = y1; y <= y2; y++)
            if (!vert[y][x1] || !vert[y][x2])
                matches = 0
        for (x = x1; x <= x2; x++)
            if (!horiz[y1][x] || !horiz[y2][x])
                matches = 0
        if (matches)
            count += 1
    }
    print count
}

Tags:

construct:add
construct:assignment
construct:boolean
construct:comment
construct:continue
construct:for-loop
construct:if
construct:indexed-access
construct:logical-or
construct:nested-loop
construct:number
construct:parameter
construct:print
construct:string
construct:variable
paradigm:imperative
technique:boolean-logic
technique:looping
technique:type-conversion
construct:explicit-conversion
iHiD commented 10 months ago

Exercise: list-ops

Code

@namespace "listops"

# Append to a list all the elements of another list.
# Or append to a list a single new element
function append(list, item_or_list) {
    # print awk::typeof(item_or_list)
    if (awk::typeof(item_or_list) == "array")
        for (i in item_or_list)
            append(list, item_or_list[i])
    else
        list[length(list) + 1] = item_or_list
}

# Concatenate is flattening a list of lists one level
function concat(list, result) {
    for (i in list)
        append(result, list[i])
}

# Only the list elements that pass the given function.
function filter(list, funcname, result) {
    for (i in list)
        if (@funcname(list[i]))
            append(result, list[i])
}

# Transform the list elements, using the given function, into a new list.
function map(list, funcname, result) {
    for (i in list)
        append(result, @funcname(list[i]))
}

# Left-fold the list using the function and the initial value.
function foldl(list, funcname, initial) {
    result = initial
    for (i in list)
        result = @funcname(result, list[i])
    return result
}

# Right-fold the list using the function and the initial value.
function foldr (list, funcname, initial,   rev) {
    array::init(rev)
    reverse(list, rev)
    result = initial
    for (i in rev)
        result = @funcname(rev[i], result)
    return result
}

# the list reversed
function reverse (list, result) {
    cur = length(list)
    for (i in list)
        result[cur--] = list[i]
}

Tags:

construct:add
construct:assignment
construct:boolean
construct:comment
construct:for-loop
construct:function
construct:index
construct:invocation
construct:if
construct:indexed-access
construct:logical-or
construct:number
construct:parameter
construct:print
construct:string
construct:variable
paradigm:imperative
technique:boolean-logic
technique:looping
technique:recursion
iHiD commented 10 months ago

Exercise: two-bucket

Code

@include "assert"
@include "assert"
BEGIN {
    FS=","
}

function push(a, b, c) {
    key = b FS c
    value = a FS b FS c
    if (key in visited) return
    visited[key] = 1
    q[++j] = value
}

function min(a, b) { return a < b ? a : b; }
{
    i = j = 0
    a = $1
    b = $2
    d = $3
    q[0] = 1 "," ($4 == "one" ? a : 0) "," ($4 == "two" ? b : 0)

    # BFS
    while (i <= j) {
        split(q[i++], x)
        n = x[1]
        x_a = x[2]
        x_b = x[3]
        assert(x_a >= 0, "invalid a")
        assert(x_b >= 0, "invalid b")

        # invalid state
        if ($4 == "one" && x_a == 0 && x_b == b) continue
        if ($4 == "two" && x_a == a && x_b == 0) continue

        if (x_a == d) {
            print n FS "one" FS x_b
            exit 0
        }

        if (x_b == d) {
            print n FS "two" FS x_a
            exit 0
        }

        n2 = n+1

        # pour a into b
        poured = min(x_a, b - x_b)
        push(n2, (x_a - poured), (x_b + poured))

        # pour b into a
        poured = min(x_b, a - x_a)
        push(n2, (x_a + poured), (x_b - poured))

        # empty a
        push(n2, 0, x_b)

        # empty b
        push(n2, x_a, 0)

        # fill a
        push(n2, a, x_b)

        # fill b
        push(n2, x_a, b)
    }

    print "invalid goal"
    exit 1
}

Tags:

No tags generated

iHiD commented 10 months ago

Exercise: run-length-encoding

Code

function encode (str,   current, count, chars, encoded, i) {
    n = split(str, chars, "")
    current = chars[1]
    count = 1
    encoded = ""
    for (i = 2; i <= n; i++) {
        if (chars[i] != current) {
            encoded = encoded (count > 1 ? count : "") current
            current = chars[i]
            count = 1
        } else {
            count++
        }
    }
    encoded = encoded (count > 1 ? count : "") current
    return encoded
}
function decode (str,   count, chars, decoded, i) {
    n = split(str, chars, "")
    count = ""
    decoded = ""
    for (i = 1; i <= n; i++) {
        if (chars[i] ~ "[[:digit:]]") {
            count = count chars[i]
        } else {
            count = count == "" ? 1 : count * 1
            for (j = 1; j <= count; j++) decoded = decoded  chars[i]
            count = ""
        }
    }
    return decoded
}
{
    print @type($0)
}

Tags:

construct:assignment
construct:bitwise-xor
construct:boolean
construct:conditional
construct:for-loop
construct:function
construct:if
construct:indexing
construct:invocation
construct:number
construct:parameter
construct:return
construct:string
construct:ternary
construct:variable
construct:visibility-modifiers
paradigm:imperative
paradigm:functional
paradigm:reflective
technique:bit-manipulation
technique:bit-shifting
technique:boolean-logic
technique:looping
uses:@type
iHiD commented 10 months ago

Exercise: secret-handshake

Code

#!/usr/bin/env gawk -f

BEGIN {
    size = split("wink,double blink,close your eyes,jump", actions, ",")
}

{
    for (i = 1; i <= size; i++)
        if (and($1, lshift(1, i - 1)))
            handshake[i] = actions[i]

    PROCINFO["sorted_in"] = and($1, 16) ? "@ind_num_desc" : "@ind_num_asc"
    for (i in handshake) result = result handshake[i] ","

    print gensub(/,$/, "", "g", result)
}

Tags:

construct:assignment
construct:beginning-of-line
construct:bitwise-and
construct:bitwise-left-shift
construct:boolean
construct:comment
construct:conditional
construct:for-loop
construct:function
construct:if
construct:indexed-access
construct:invocation
construct:loop
construct:number
construct:parameter
construct:print
construct:regex
construct:string
construct:subtract
construct:ternary
construct:variable
construct:visibility
paradigm:imperative
paradigm:functional
paradigm:reflective
technique:bit-manipulation
technique:bit-shifting
technique:looping
technique:regular-expression
iHiD commented 10 months ago

Exercise: space-age

Code

#!/usr/bin/env gawk -f

BEGIN {
    periods["Mercury"] = 0.2408467
    periods["Venus"] = 0.61519726
    periods["Earth"] = 1
    periods["Mars"] = 1.8808158 
    periods["Jupiter"] = 11.862615 
    periods["Saturn"] = 29.447498 
    periods["Uranus"] = 84.016846 
    periods["Neptune"] = 164.79132
    SPY = 60 * 60 * 24 * 365.25
}

{
    if (!periods[$1]) { print "not a planet"; exit 1}
    printf "%.2f", $2 / periods[$1] / SPY
}

Tags:

construct:assignment
construct:begin-end
construct:comment
construct:divide
construct:double
construct:exit
construct:floating-point-number
construct:if
construct:implicit-conversion
construct:indexed-access
construct:invocation
construct:lambda
construct:number
construct:print
construct:variable
construct:visibility-modifiers
paradigm:functional
paradigm:imperative
paradigm:reflective
technique:divide-and-conquer
technique:higher-order-functions
iHiD commented 10 months ago

Exercise: nth-prime

Code

BEGIN {
    if (n < 1) {
        print("invalid input")
        exit(1)
    }
    if (n == 1) {
        print(2)
        exit(0)
    }

    primes[1] = 2
    count = 1
    candidate = 1

    while (count < n) {
        while (1) {
            candidate += 2
            is_prime = 1
            i = 1
            while (primes[i] <= sqrt(candidate)) {
                if (candidate % primes[i] == 0) {
                    is_prime = 0
                    break
                }
                i++
            }
            if (is_prime) break
        }
        primes[++count] = candidate
    }

    print primes[n]
}

Tags:

construct:assignment
construct:break
construct:if
construct:indexing
construct:invocation
construct:method
construct:number
construct:parameter
construct:print
construct:variable
construct:visibility-modifiers
construct:while-loop
paradigm:imperative
paradigm:reflective
technique:looping
iHiD commented 10 months ago

Exercise: triangle

Code

#!/usr/bin/env gawk -f

$1 + $2 < $3 || $1 + $3 < $2 || $2 + $3 < $1 { print "false"; next }

{
    delete sides
    for (i = 1; i <= 3; ++i) sides[$i] = 1
    uniq = length(sides)
}
uniq == 1 && $1 == 0 { print "false"; next }
type == "equilateral" { print uniq == 1 ? "true" : "false" }
type == "isosceles" { print uniq <= 2 ? "true" : "false" }
type == "scalene" { print uniq == 3 ? "true" : "false" }

Tags:

construct:add
construct:assignment
construct:boolean
construct:delete
construct:executable
construct:expression
construct:for-loop
construct:function
construct:implicit-conversion
construct:index
construct:invocation
construct:logical-and
construct:logical-or
construct:number
construct:parameter
construct:print
construct:string
construct:ternary
construct:variable
construct:visibility-modifiers
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:boolean-logic
technique:looping
iHiD commented 10 months ago

Exercise: rotational-cipher

Code

#!/usr/bin/env gawk -f

@load "ordchr"

BEGIN { FS = "" }

{
    for (i = 1; i <= NF; i++) {
        ordinal = ord($i)

        if (ordinal >= 65 && ordinal <= 96)
            printf chr(65 + ((ordinal - 65 + distance) % 26))
        else if (ordinal >= 97 && ordinal <= 122)
            printf chr(97 + ((ordinal - 97 + distance) % 26))
        else
            printf $i
    }
}

Tags:

construct:add
construct:assignment
construct:beginning
construct:boolean
construct:for-loop
construct:if
construct:implicit-conversion
construct:invocation
construct:logical-and
construct:number
construct:parameter
construct:printf
construct:string
construct:subtract
construct:variable
construct:visibility-modifiers
paradigm:imperative
paradigm:logical
paradigm:reflective
technique:boolean-logic
technique:looping
iHiD commented 10 months ago

Exercise: rotational-cipher

Code

function rot(letter, alphabet, n){
    split(alphabet, arr_alphabet, "")
    #for (i in arr_alphabet) print "at", i, "there is", arr_alphabet[i]
    start = index(alphabet, letter) - 1
    end = (start + n) % 26
    #print "start :", start, "rot :", n, "end :", end, "<", letter, ">", ": ------>", arr_alphabet[end + 1]
    return arr_alphabet[end + 1]
}
BEGIN {
    FS = ""
}
{
    alphabet = "abcdefghijklmnopqrstuvwxyz"
    almaj = toupper(alphabet)
    res = ""
    for (i = 1; i <= NF; i++){
        if ($i ~ /[a-zA-Z]/)
            res = res""rot($i, ($i == toupper($i) ? almaj : alphabet), distance)
        else
            res = res""$i
    }
    print res
}

Tags:

construct:add
construct:assignment
construct:comment
construct:for-loop
construct:function
construct:if
construct:indexed-access
construct:invocation
construct:parameter
construct:return
construct:string
construct:subtract
construct:ternary
construct:variable
construct:visibility-modifiers
paradigm:imperative
paradigm:functional
paradigm:object-oriented
technique:looping
uses:RegExp
iHiD commented 10 months ago

Exercise: resistor-color-trio

Code

#!/usr/bin/env gawk -f

BEGIN {
    split("black brown red orange yellow green blue violet grey white", bands)
    split("kilo mega giga", prefixes)
}

{
    ohms = (resistance($1) * 10 + resistance($2)) * 10 ** resistance($3)
    for (; ohms && ohms % 1000 == 0; ohms /= 1000)
        idx++
    print ohms " " prefixes[idx] "ohms"
}

function resistance(color) {
    for (i = 1; i <= length(bands); i++)
        if (bands[i] == color) return i - 1

    print "Invalid color: " color
    exit(1)
}

Tags:

construct:assignment
construct:beginning-of-line
construct:boolean
construct:double
construct:exit
construct:floating-point-number
construct:for-loop
construct:function
construct:if
construct:implicit-conversion
construct:index
construct:invocation
construct:logical-and
construct:method
construct:multiply
construct:number
construct:parameter
construct:print
construct:return
construct:string
construct:subtract
construct:variable
construct:visibility-modifiers
paradigm:imperative
paradigm:functional
paradigm:object-oriented
technique:boolean-logic
technique:looping
iHiD commented 10 months ago

Exercise: atbash-cipher

Code

BEGIN {
    FS = ""
    alphabet = "abcdefghijklmnopqrstuvwxyz"
    cypher = "zyxwvutsrqponmlkjihgfedcba"
    split(alphabet, alphabet_arr, "")
    split(cypher, cypher_arr, "")

}
/The quick brown fox jumps over the lazy dog./ {
    print "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt"
    next
}
{
    blank = 0
    for (i = 1; i <= NF; i++){
        if ($i ~ /[[:alpha:]]/)
            res = direction == "encode" ? res""cypher_arr[index(alphabet, tolower($i))] : res""alphabet_arr[index(cypher, tolower($i))]
        else if ($i ~ /[[:digit:]]/)
            res = res""$i
        if ($i ~ /[[:alnum:]]/ && i != NF && (length(res) - blank) % 5 == 0 && direction == "encode"){
            res = res" "
            ++blank
        }
    }
    print res
}

Tags:

construct:assignment
construct:boolean
construct:comment
construct:for-loop
construct:if
construct:implicit-conversion
construct:index
construct:invocation
construct:logical-and
construct:number
construct:parameter
construct:print
construct:regex
construct:string
construct:ternary
construct:variable
construct:visibility-modifiers
paradigm:imperative
paradigm:declarative
paradigm:functional
paradigm:object-oriented
technique:boolean-logic
technique:looping
technique:regular-expression
iHiD commented 10 months ago

Exercise: say

Code

function say10(n) {
    switch(n) {
        case 0: return ""
        case 1: return "one"
        case 2: return "two"
        case 3: return "three"
        case 4: return "four"
        case 5: return "five"
        case 6: return "six"
        case 7: return "seven"
        case 8: return "eight"
        case 9: return "nine"
    }
}
function join(n, sep) { return n ? sep : "" }

function say100(n) {
    if (n >= 90)      { return "ninenty" join(n%10, "-") say10(n % 10) }
    else if (n >= 80) { return "eighty"  join(n%10, "-") say10(n % 10) }
    else if (n >= 70) { return "seventy" join(n%10, "-") say10(n % 10) }
    else if (n >= 60) { return "sixty"   join(n%10, "-") say10(n % 10) }
    else if (n >= 50) { return "fifty"   join(n%10, "-") say10(n % 10) }
    else if (n >= 40) { return "forty"   join(n%10, "-") say10(n % 10) }
    else if (n >= 30) { return "thirty"  join(n%10, "-") say10(n % 10) }
    else if (n >= 20) { return "twenty"  join(n%10, "-") say10(n % 10) }
    else if (n >= 10) {
        switch(n) {
            case 10: return "ten"
            case 11: return "eleven"
            case 12: return "twelve"
            case 13: return "thirteen"
            case 14: return "fourteen"
            case 15: return "fifteen"
            case 16: return "sixteen"
            case 17: return "seventeen"
            case 18: return "eighteen"
            case 19: return "nineteen"
        }
    } else { return say10(n) }
}
function say1000(n) {
    if (n >= 100) { return say10(int(n/100)) " hundred" join(n%10, " ") say100(n % 100) }
    else { return say100(n) }
}
BEGIN {
    num[1000] = "thousand"
    num[1000000] = "million"
    num[1000000000] = "billion"
}

$0 < 0 || $0 >= 1000000000000 {
    print("input out of range")
    exit(1)
}

$0 == 0 { print("zero"); next }

{
    PROCINFO["sorted_in"] = "@ind_num_desc"
    n = strtonum($0)
    out = ""
    for(m in num) {
        if (n - m >= 0) {
            div = int(n/m)
            rem = n % m
            out = out say1000(div) " " num[m] join(rem, " ")
            n = rem
        }
    }
    if (n) out = out say1000(n)
    print out
}

Tags:

construct:assignment
construct:boolean
construct:case
construct:divide
construct:double
construct:else
construct:exit
construct:floating-point-number
construct:for-loop
construct:function
construct:if
construct:implicit-conversion
construct:indexed-access
construct:initializer
construct:integral-number
construct:invocation
construct:logical-or
construct:number
construct:object
construct:parameter
construct:return
construct:string
construct:subtract
construct:switch
construct:ternary
construct:variable
construct:visibility-modifiers
paradigm:imperative
paradigm:object-oriented
technique:boolean-logic
technique:looping
iHiD commented 10 months ago

Exercise: variable-length-quantity

Code

# These variables are initialized on the command line (using '-v'):
# - action
function assert(cond, msg) {
    if (!cond) {
        print(msg)
        exit(1)
    }
}

BEGIN {
    assert(action == "encode" || action == "decode", "unknown action")
    mask = 127
}

action == "encode" {
    fst = 0
    for(i = 1; i <= NF; i++) {
        n = strtonum("0x" $i)
        out = ""
        for(seg = 0;;seg++) {
            segment = and(n, mask)
            segment += seg ? 128 : 0
            out = sprintf(seg ? " " : "") out
            out = sprintf("%02X", segment) out
            n = rshift(n, 7)
            if (!n) break;
        }
        printf(fst++ ? " " : "")
        printf(out)
    }
}

action == "decode" {
    fst = 0
    n = 0
    inprogress = 0
    for(i = 1; i <= NF; i++) {
        b = strtonum("0x" $i)
        n = or(lshift(n, 7), and(b, 127))
        if (and(b,128)) {
            inprogress = 1
        } else {
            inprogress = 0
            printf(fst++ ? " " : "")
            printf("%02X", n)
            n = 0
        }
    }
    if (inprogress) {
        print("incomplete byte sequence")
        exit(1)
    }
}

Tags:

construct:assignment
construct:bitwise-and
construct:bitwise-left-shift
construct:bitwise-or
construct:boolean
construct:break
construct:comment
construct:conditional
construct:exit
construct:for-loop
construct:function
construct:if
construct:implicit-loop
construct:invocation
construct:logical-or
construct:number
construct:parameter
construct:print
construct:string
construct:ternary
construct:variable
construct:visibility
paradigm:imperative
paradigm:procedural
technique:bit-manipulation
technique:bit-shifting
technique:boolean-logic
technique:looping
iHiD commented 10 months ago

Exercise: largest-series-product

Code

#!/usr/bin/env gawk -f

BEGIN { FS=","  }

$1 ~ /[a-zA-Z]/     { print "input must only contain digits";          exit -1 }
$2 < 0              { print "span must not be negative";               exit -1 }
$2 > length($1)     { print "span must be smaller than string length"; exit -1 }

$2 <= length($1) {
    split($1, nums, "")
    max = 0
    for(i=1; i+$2<=length($1)+1; i++){       
        mult = 1
        for(j=0; j<$2; j++) { 
            mult = mult * nums[j+i]
        }
        if (mult > max) max = mult
    }
    print max
}

Tags:

construct:assignment
construct:beginning
construct:comment
construct:constructor
construct:exit
construct:for-loop
construct:if
construct:indexed-access
construct:invocation
construct:method
construct:number
construct:parameter
construct:print
construct:regex
construct:string
construct:variable
construct:visibility-modifiers
paradigm:imperative
paradigm:reflective
technique:looping
technique:regular-expression
iHiD commented 10 months ago

Exercise: roman-numerals

Code

#!/usr/bin/env gawk -f

function set(base, string) {
    n = split(string, chars)
    for (i = 1; i <= n; i++) vals[base * 10^(i-1)] = chars[i]
}
function concat(a, b) {
    vals[a - b] = vals[b] vals[a]
    vals[a/2 - b] = vals[b] vals[a/2]
}

BEGIN {
    # Set characters.
    set(1, "I X C M")
    set(5, "V L D")
    # Set compound characters.
    for (i = 0; i < 3; i++) concat(1 * 10^(i+1), 10^i)
    PROCINFO["sorted_in"] = "@ind_num_desc"
}

{
    num = $1
    out = ""
    for (i in vals) {
        while (num >= i + 0) {
            out = out vals[i]
            num -= i
        }
    }
    print out
}

Tags:

construct:add
construct:assignment
construct:comment
construct:divide
construct:exponentiation
construct:for-loop
construct:function
construct:indexing
construct:invocation
construct:loop
construct:number
construct:parameter
construct:property
construct:string
construct:subtract
construct:variable
construct:visibility-modifiers
paradigm:imperative
paradigm:functional
paradigm:object-oriented
technique:looping
iHiD commented 10 months ago

Exercise: pop-count

Code

# awk implements bitwise functionality with functions, not operators.
# https://www.gnu.org/software/gawk/manual/html_node/Bitwise-Functions.html

function popCount(n,    c) {
    c = 0
    while (n > 0) {
        c += and(n, 1)
        n = rshift(n, 1)
    }
    return c
}

NF {print popCount($1)}

Tags:

construct:assignment
construct:bitwise-and
construct:function
construct:invocation
construct:loop
construct:number
construct:parameter
construct:return
construct:variable
construct:visibility
paradigm:imperative
paradigm:functional
paradigm:reflective
technique:bit-manipulation
technique:bit-shifting
technique:looping
ErikSchierboom commented 10 months ago

This is an automated comment

Hello :wave: Next week we're going to start using the tagging work people are doing on these. If you've already completed the work, thank you! If you've not, but intend to this week, that's great! If you're not going to get round to doing it, and you've not yet posted a comment letting us know, could you please do so, so that we can find other people to do it. Thanks!

ErikSchierboom commented 9 months ago

Thanks for the help! We've updated the tags.