Rules: no spoilers.

The other rules are made up as we go along.

Share code by link to a forge, home page, pastebin (Eric Wastl has one here) or code section in a comment.

  • datarama@awful.systems
    link
    fedilink
    English
    arrow-up
    4
    ·
    edit-2
    1 year ago

    I made one solution in Python, and another in Scheme. Here are the regex-related parts.

    Python:

    spoiler

    Here is a regex:·

    rx = "(?=(one|two|three|four|five|six|seven|eight|nine|1|2|3|4|5|6|7|8|9))"
    

    The leading ?= is a lookahead assertion. If we can read any of the subexpressions one,two,…, it produces the empty string as a match, with the actual matched string as a capturing group. Python’s re module has a findall function which finds all non-overlapping matches in a string … but since it’s the matches (not the capturing groups) that have to be non-overlapping, and lookahead produces empty strings as matches, we have re.findall(rx,"twone") == ["two","one"] and re.findall(rx,"sevenineight") == ["seven","nine","eight"]. Empty string doesn’t overlap!

    So here’s the core of the solution:

    def solve(s):
        m = [numeralize(t) for t in re.findall(rx, s)]
        return int(m[0] + m[len(m)-1])
    

    Where numeralize is a simple function that converts “eight” into “8”. Not to the number 8, since we want to do string concatenation on them rather than addition. :-)

    I haven’t written any Perl in ages, so I have no idea if Perl has an analogue to findall.


    Scheme:

    spoiler

    …but I do know that Scheme, at least CHICKEN, doesn’t. Here is the best my currently badly fever-addled brain could come up with:

    I’m using the irregex library. I start by building an irregex out of a SRE (Scheme Regular Expression):

    (define ir (sre->irregex '(seq bos (or "one" "two" "three" "four" "five" "six" "seven" "eight" "nine"·
                                           "1" "2" "3" "4" "5" "6" "7" "8" "9"))))
    

    This matches from the beginning of the string (hence bos), and doesn’t use any fancy lookahead. It only matches one string.

    Here is a little recursive function that finds all matches using the above:

    (define (all-matches s)
      (if (= (string-length s) 0)
        '()
        (let ((matches (irregex-search ir s)))
          (if (not matches)
            (all-matches (string-drop s 1))
            (cons (irregex-match-substring matches)
                  (all-matches (string-drop s 1)))))))
    

    It simply tries making a match from the beginning, and then continues making one from a substring with the first character hacked off, until it ends up with the empty string. Not exactly my proudest Scheme code, but it works.

    Using that, the analogue of the solution I did for the Python version is:

    (define (solve s)
      (let ((m (all-matches s)))
        (string->number
          (string-append (numeralize (list-ref m 0))
                         (numeralize (list-ref m (- (length m) 1)))))))
    

    Again, not my proudest Scheme code! I am currently nursing a fever and trying not to sneeze and cough my lungs to pieces.

    • self@awful.systemsM
      link
      fedilink
      English
      arrow-up
      4
      ·
      1 year ago

      fuck yes scheme. you might have just inspired me to write some Lisp Machine Lisp solutions, since I might need a Lisp Machine codebase to test one of my side projects

      • datarama@awful.systems
        link
        fedilink
        English
        arrow-up
        4
        ·
        1 year ago

        I have a toy Lisp implemenation I used to work on, but I’ve lost the motivation.

        Not that I think one more little virtual machine project makes a material difference either way, but I really don’t feel like spending my free time writing nontrivial code for loathsome AI companies.

    • gerikson@awful.systemsOP
      link
      fedilink
      English
      arrow-up
      4
      ·
      1 year ago

      Re Perl findall, I used this regex in my “clean” solution which I didn’t post because I figure it’s more honest to submit what worked, not the smart stuff you found out later.

      regex

      # find all numerals and number in English from the string $line and put them into the array @spelled my @spelled = ( $line =~ (m/(?=(\d{1}|one|two|three|four|five|six|seven|eight|nine))/g );