exercism / raku

Exercism exercises in Raku
https://exercism.org/tracks/raku
MIT License
22 stars 33 forks source link

Building a training set of tags for raku #674

Closed iHiD closed 1 year ago

iHiD commented 1 year 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 1 year ago

Exercise: two-fer

Code

unit module TwoFer:ver<2>;

sub two-fer ($name?) is export {
    "One for {$name // 'you'}, one for me."
}

Tags:

construct:string-interpolation
construct:module
construct:optional-parameter
construct:parameter
construct:routine
construct:subroutine
construct:template-string
construct:unit
construct:visibility-modifier
paradigm:declarative
paradigm:functional
paradigm:object-oriented
iHiD commented 1 year ago

Exercise: leap

Code

class Leap {
    method is_leap($year) {
        given $year {
            when $year % 400 == 0 { True}
            when $year % 100 == 0 { False}
            when $year % 4 == 0 { True }
            default {False }
        }
    }
}

Tags:

construct:boolean
construct:class
construct:default
construct:given
construct:method
construct:parameter
construct:when
construct:year
paradigm:object-oriented
iHiD commented 1 year ago

Exercise: etl

Code

unit module ETL:ver<1>;

no precompilation;

sub transform (%old-score) is export {
    my Int:D %new-score{Str:D} = %old-score.invert.map: {.key.fc => .value}
}

Tags:

construct:assignment
construct:class
construct:export
construct:hash
construct:invocant
construct:lambda
construct:map
construct:method
construct:module
construct:named-argument
construct:parameter
construct:signature
construct:sub
construct:subscript
construct:variable
construct:visibility
paradigm:functional
paradigm:object-oriented
technique:higher-order-functions
uses:Hash
uses:Mapping
iHiD commented 1 year ago

Exercise: etl

Code

unit module ETL:ver<2>;

no precompilation;

sub transform (%input) is export {
  my Int:D %output{Str:D};
  %input.kv.map(-> $val, @chars { for @chars -> $char { %output{lc($char).Str}= $val.Int }});
  return %output;
}

Tags:

construct:assignment
construct:for/hash
construct:hash
construct:invocable
construct:lambda
construct:map
construct:method
construct:module
construct:parameter
construct:return
construct:signature
construct:sub
construct:subscript
construct:variable
construct:visibility
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:higher-order-functions
technique:looping
uses:Hash
iHiD commented 1 year ago

Exercise: nucleotide-count

Code

unit module NucleotideCount:ver<1>;

sub nucleotide-count ($strand) is export {
    die when $strand !~~ /^<[ACGT]>*$/;
    $strand.comb.Bag
}

Tags:

construct:bag
construct:char
construct:die
construct:export
construct:is
construct:method
construct:module
construct:parameter
construct:regex
construct:routine
construct:sub
construct:unit
construct:variable
construct:when
paradigm:declarative
paradigm:functional
paradigm:object-oriented
technique:exceptions
technique:regular-expression
uses:Bag
iHiD commented 1 year ago

Exercise: nucleotide-count

Code

unit module NucleotideCount:ver<2>;

sub nucleotide-count ($strand) is export {

  # Define hash to return (with type constraints -- required by test suite)
  my Int:D %counts{Str:D} = ('A' => 0,
                             'T' => 0,
                             'C' => 0,
                             'G' => 0);

  # If the strand is not empty, parse it
  if $strand ne "" {

    # Split the strand into bases (skip any empty characters)
    my @bases = split("",:skip-empty, $strand);

    # For each base in the bases array...
    for @bases -> $base {

      # If the base exists in the hash, increment the count of it
      if %counts{$base}:exists {
        %counts{$base}++;
      }

      # If it contains an invalid character, die with a message
      # (Not the most efficient way if you have a long strand and an invalid
      # character late in the strand)
      else {
        die "Invalid nucleotide in strand";
      }
  }

  # Return our count hash
  return %counts;
  }
}

Tags:

construct:assignment
construct:comment
construct:die
construct:for/hash
construct:hash
construct:if
construct:implicit-return
construct:indexing
construct:invocable
construct:method
construct:number
construct:return
construct:string
construct:sub
construct:variable
construct:visibility
paradigm:imperative
paradigm:functional
paradigm:object-oriented
technique:exceptions
technique:looping
uses:Hash
iHiD commented 1 year ago

Exercise: clock

Code

unit class Clock:ver<1>;

has $.hour;
has $.minute;

method time() {
    my $minute_str = $!minute % 60;
    my $hour_str = "{($!hour + $!minute div 60) % 24}";
    $hour_str = "0" ~ $hour_str if $hour_str.comb.elems == 1;
    $minute_str = "0" ~ $minute_str if $minute_str.comb.elems == 1;
    return($hour_str ~ ":" ~ $minute_str)
}

method add-minutes($add) {
    $!minute += $add;
    self;
}

Tags:

construct:add
construct:assignment
construct:class
construct:has
construct:if
construct:implicit-method
construct:method
construct:number
construct:parameter
construct:return
construct:string
construct:template-string
construct:unit
construct:variable
construct:visibility-modifier
paradigm:imperative
paradigm:object-oriented
iHiD commented 1 year ago

Exercise: flatten-array

Code

unit module FlattenArray:ver<1>;

sub flatten-array(@input) is export {
    [gather {
        for @input {
            when * ~~ Array { take $_ for flatten-array($_) }
            when * ~~ Any:D { take $_ }
        }
    }]
}

Tags:

construct:array
construct:class
construct:for
construct:gather
construct:invocable
construct:method
construct:module
construct:parameter
construct:sub
construct:submethod
construct:take
construct:trait
construct:unit
construct:version
construct:when
paradigm:functional
paradigm:object-oriented
technique:laziness
technique:looping
technique:recursion
iHiD commented 1 year ago

Exercise: accumulate

Code

unit class Accumulate;

method accumulate(Array $elems, Sub $fn --> Array) {
    my @results;
    @results.push: $fn($_) for $elems.values;
    @results
}

Tags:

construct:class
construct:for
construct:method
construct:my
construct:parameter
construct:signature
construct:sub
construct:submethod
construct:unit
construct:variable
construct:visibility
paradigm:object-oriented
technique:looping
iHiD commented 1 year ago

Exercise: grains

Code

unit module Grains:ver<1>;

subset Square of Int where * ~~ 0 ^.. 64;

sub grains-on-square(Square $n) is export {
    ($n - 1).exp(2);
}

sub total-grains() is export {
    64.exp(2) - 1;
}

Tags:

construct:subtract
construct:export
construct:int
construct:integral-number
construct:invocant
construct:method
construct:module
construct:number
construct:parameter
construct:subset
construct:subtraction
construct:unit
construct:visibility
paradigm:object-oriented
iHiD commented 1 year ago

Exercise: all-your-base

Code

unit module AllYourBase:ver<3>;

sub from-base($base, @digits) {
    @digits.reverse.map({$_ * ($base ** $++) }).sum;
}

sub to-base($base, $value is copy) {
    my @digits = $value.polymod($base xx *).reverse;
    return @digits || [0];
}

sub convert-base (
        :%bases!  where { %bases<to from>.all > 1 },
        :@digits! where { .all ~~ 0..^%bases<from> }
) is export {
    to-base(%bases<to>, from-base(%bases<from>, @digits));
}

Tags:

construct:assignment
construct:auto-increment
construct:boolean
construct:copy
construct:expression
construct:implicit-return
construct:indexing
construct:invocant-capture
construct:lambda
construct:list
construct:logical-or
construct:map
construct:module
construct:named-argument
construct:number
construct:parameter
construct:polymod
construct:range
construct:return
construct:signature
construct:sub
construct:subroutine
construct:sum
construct:template
construct:using-declaration
construct:variable
construct:where
construct:xx
paradigm:functional
paradigm:imperative
paradigm:reflective
technique:boolean-logic
technique:higher-order-functions
technique:math
iHiD commented 1 year ago

Exercise: anagram

Code

use v6;

sub ssort ($word) {
   $word.uc.comb(/./).sort.join('');
}

class Anagram {
   method match ($main, @list) {
      my $muc  = $main.uc;
      my $mref = ssort($main);
      return [@list.grep: { ssort($_) eq $mref && .uc ne $muc}];
   }
}

Tags:

construct:class
construct:invocable
construct:join
construct:method
construct:parameter
construct:return
construct:routine
construct:subexpression
construct:submethod
construct:use
construct:variable
construct:visibility
paradigm:object-oriented
technique:higher-order-functions
iHiD commented 1 year ago

Exercise: allergies

Code

my @allergies =
    :1eggs,
    :2peanuts,
    :4shellfish,
    :8strawberries,
    :16tomatoes,
    :32chocolate,
    :64pollen,
    :128cats;

sub allergic-to(UInt $score, Str $substance --> Bool) is export {
    so $score +& %@allergies{$substance}
}

sub list-allergies(UInt $score --> Seq) is export {
    @allergies».key.grep: { allergic-to($score, $^substance) }
}

Tags:

construct:add
construct:assignment
construct:bitwise-and
construct:hash
construct:indexing
construct:invocant
construct:is export
construct:is list
construct:is number
construct:is parameterized type
construct:is phaser
construct:is subscriptable
construct:is subroutine
construct:method
construct:number
construct:parameter
construct:signature
construct:string
construct:subscript
construct:subtraction
construct:table
construct:template
construct:variable
paradigm:functional
paradigm:imperative
paradigm:metaprogramming
paradigm:reflective
technique:bit manipulation
technique:higher-order-functions
iHiD commented 1 year ago

Exercise: allergies

Code

use v6;
unit module Allergies;
constant @SUBSTANCES = <
    eggs     peanuts   shellfish strawberries
    tomatoes chocolate pollen    cats
>;
constant %VALUE-OF = hash @SUBSTANCES Z=> (1,2,4 ... *) ;

sub allergic-to  ( $score, $substance, ) is export {
    $_ <= $score % (2*$_)  with %VALUE-OF{$substance};
}

sub list-allergies ( $score ) is export {
    #($score.polymod( 2 xx * )  Z&& @SUBSTANCES).grep: *.so 
    # this works too, but it is confusing

    @SUBSTANCES.grep: { allergic-to( $score, $_ ) }
}

Tags:

construct:assignment
construct:bitwise-and
construct:comment
construct:constant
construct:export
construct:hash
construct:invocant
construct:list
construct:module
construct:multiply
construct:naked-underscore-parameter
construct:parameter
construct:routine
construct:subscript
construct:template
construct:use
construct:variable
construct:with
paradigm:functional
paradigm:imperative
paradigm:metaprogramming
paradigm:object-oriented
technique:bit-manipulation
technique:bit-shifting
technique:higher-order-functions
uses:Hash
uses:Variable:Constant Assignment
iHiD commented 1 year ago

Exercise: linked-list

Code

class LinkedList is export {

    class Node {
        has Mu $.value is rw;
        has Node $.prev is rw;
        has Node $.next is rw;
    }

    has Node $!first;
    has Node $!last;

    method unshift(Mu $value --> Nil) {
        my $newNode = Node.new(:$value);
        if not $!first {
            $!first = $newNode;
            $!last = $newNode;
            $newNode.prev = Nil;
            $newNode.next = Nil;
        } else {
            self!before($!first, $newNode);
        }
    }

    method push(Mu $value --> Nil) {
        if not $!last {
            self.unshift($value);
        } else {
            self!after($!last, Node.new(:$value));
        }
    }

    method pop(--> Mu) {
        self!remove($!last);
    }

    method shift(--> Mu) {
        self!remove($!first);
    }

    method !after(Node $node, Node $newNode) {
        $newNode.prev = $node;
        if not $node.next {
            $newNode.next = Nil;
            $!last = $newNode;
        } else {
            $newNode.next = $node.next;
            $node.next.prev = $newNode;
        }
        $node.next = $newNode;
    }

    method !before(Node $node, Node $newNode) {
        $newNode.next = $node;
        if not $node.prev {
            $newNode.prev = Nil;
            $!first = $newNode;
        } else {
            $newNode.prev = $node.prev;
            $node.prev.next = $newNode;
        }
        $node.prev = $newNode;
    }

    method !remove(Node $node --> Mu) {
        if not $node.prev {
            $!first = $node.next;
        } else {
            $node.prev.next = $node.next;
        }
        if not $node.next {
            $!last = $node.prev;
        } else {
            $node.next.prev = $node.prev;
        }
        $node.value
    }
}

Tags:

construct:assignment
construct:class
construct:constructor
construct:field
construct:if
construct:invocable
construct:method
construct:named-argument
construct:nested-class
construct:parameter
construct:property
construct:variable
construct:visibility-modifiers
paradigm:object-oriented
iHiD commented 1 year ago

Exercise: acronym

Code

unit module Acronym:ver<2>;

sub abbreviate ($_) is export {
  S:g/(\w)\w*\W*/$0/ andthen .uc
}

Tags:

construct:andthen
construct:assignment
construct:export
construct:invocant method
construct:module
construct:parameter
construct:regex
construct:routine
construct:substitution
construct:substitution reference
construct:unit
construct:variable
construct:visibility
paradigm:imperative
paradigm:object-oriented
technique:regular expression
uses:Variable interpolation in regex
iHiD commented 1 year ago

Exercise: roman-numerals

Code

unit module RomanNumerals:ver<1>;

constant $NUM2ROMAN = 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 Zbut <M CM D CD C XC L XL X IX V IV I> ;

sub iter (
    [
        $number,
        $converted,
        [ $cp, *@convert ],
    ]
) {
    with $number.polymod( $cp ) {
        .[0], $cp x .[1], @convert
    }
}

sub to-roman ($number) is export {
    ( [$number,'',$NUM2ROMAN], &iter ... { not  .[0] }  )».[1].join;
}

Tags:

construct:assignment
construct:char
construct:constant
construct:exported-routine
construct:implicit-method
construct:invocant
construct:is
construct:join
construct:list
construct:module
construct:number
construct:parameter
construct:polymod
construct:routine
construct:signature
construct:subscript
construct:subscript-assignment
construct:variable
construct:with
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:higher-order-functions
iHiD commented 1 year ago

Exercise: binary

Code

use v6;

class Binary {
    multi method to_decimal(Str $bin where m/^\d+$/ --> Int) {
        [+] $bin.comb.reverse.kv.map({ (2**$^a) * $^b })
    }
    multi method to_decimal(Str $bin --> Int) { 0 }
}

Tags:

construct:class
construct:method
construct:multi-dispatch
construct:parameter
construct:regex
construct:sigil
construct:where
construct:invocable
construct:lambda
construct:list
construct:method
construct:multiply
construct:number
construct:parameter
construct:pattern
construct:use
construct:variable
construct:visibility
paradigm:functional
paradigm:object-oriented
technique:higher-order-functions
technique:regular-expression
uses:List
iHiD commented 1 year ago

Exercise: trinary

Code

use v6;
unit module Trinary;

subset Trinary where /^ <[ 0 .. 2 ]>* $/;

proto to-decimal ($) is export {*}

multi sub to-decimal ( Trinary $trinary ) {
    my @trinary_numbers = $trinary.flip.comb;
    my @exp_3          = 1, 3, 9 ... *;

    ( @trinary_numbers Z* @exp_3 ).sum;
}

multi sub to-decimal ( $ ) { 0 }

Tags:

construct:comma
construct:is-prototype
construct:is-subset
construct:method
construct:module
construct:multi-dispatch
construct:parameter
construct:pattern
construct:proto
construct:subset
construct:use-directive
construct:variable
paradigm:functional
paradigm:multiple-dispatch
technique:regular-expression
iHiD commented 1 year ago

Exercise: trinary

Code

sub to-decimal(Str(Cool) $input) is export {
    return 0 unless $input ~~ /^<[012]>+$/;
    $input.comb.reduce: { 3 * $^a + $^b }
}

Tags:

construct:add
construct:assignment
construct:cool-type
construct:implicit-conversion
construct:int
construct:integral-number
construct:invocant
construct:is export
construct:method
construct:multiply
construct:number
construct:parameter
construct:pattern
construct:regex
construct:return
construct:sub
construct:subroutine
construct:template
construct:unless
construct:variable
construct:visibility
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:regular-expression
technique:types
uses:Cool
ErikSchierboom commented 1 year 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!