Numbered Notes
with Raku

by Arne Sommer

Numbered Notes with Raku

[244] Published 9. July 2023.

This is my response to The Weekly Challenge #224.

Challenge #224.1: Special Notes

You are given two strings, $source and $target.

Write a script to find out if using the characters (only once) from source, a target string can be created.

Example 1:
Input: $source = "abc"
       $target = "xyz"
Output: false
Example 2:
Input: $source = "scriptinglanguage"
       $target = "perl"
Output: true
Example 3:
Input: $source = "aabbcc"
       $target = "abc"
Output: true

This is a simplified (extremely simplified, actually) version of «Good String», the first part of Challenge 221. See Subsequencially Good with Raku for my take on it.

File: special-notes
#! /usr/bin/env raku

unit sub MAIN ($source, $target);           # [1]

say $target.comb.Bag (<=) $source.comb.Bag  # [2]
  ?? 'true'                                 # [2a]
  !! 'false';                               # [2b]

[1] No where clauses on the two strings, so they can be empty.

[2] Coerce the list of individual characters (with .comb) of each string into a Bag (with bag), a hash like structure with the individual values (without duplicates, as it is hash like) in the input array as keys, and the occurences as the values.

See docs.raku.org/routine/comb for more information about comb.

See docs.raku.org/type/Bag for more information about the Bag type.

Then we use the subset (or equal) operator (<=) to check if the target characters is a subset (or equal) of the source. If it is, print 'true' [2a], and 'false' if not [2b].

See docs.raku.org/language/operators infix (<=) for more information about the subset or equal to operator (<=).

Running it:

$ ./special-notes abc xyz
false

$ ./special-notes scriptinglanguage perl
true

$ ./special-notes aabbcc abc
true

Looking good.

Let us have a go at empty strings:

$ ./special-notes "" ""
true

$ ./special-notes "" a
false

$ ./special-notes a ""
true

All three are reasonable, but one can argue about the reasonability of allowing empty strings in the first place.

Challenge #224.2: Additive Number

You are given a string containing digits 0-9 only.

Write a script to find out if the given string is additive number. An additive number is a string whose digits can form an additive sequence.

A valid additive sequence should contain at least 3 numbers. Except the first 2 numbers, each subsequent number in the sequence must be the sum of the preceding two.

Example 1:
Input: $string = "112358"
Output: true

The additive sequence can be created using the given string digits: 1,1,2,3,5,8
1 + 1 => 2
1 + 2 => 3
2 + 3 => 5
3 + 5 => 8
Example 2:
Input: $string = "12345"
Output: false

No additive sequence can be created using the given string digits.
Example 3:
Input: $string = "199100199"
Output: true

The additive sequence can be created using the given string digits: 1,99,100,199
 1 +  99 => 100
99 + 100 => 199

The first two examples deal with single digits only, so let us have a go at that:

File: additive-digit
#! /usr/bin/env raku

unit sub MAIN ($string where $string.chars > 2 && $string ~~ /^<[0..9]>*$/);  # [1]

say is-additive($string) ?? 'true' !! 'false';                                # [2]

sub is-additive ($string where $string.chars > 2 && $string ~~ /^<[0..9]>*$/) # [1a]
{
  my @digits = $string.comb;                                                  # [3]

  my $first  = @digits.shift;                                                 # [4]
  my $second = @digits.shift;                                                 # [5]

  while (@digits.elems)                                                       # [6]
  {
    my $third = @digits.shift;                                                # [7]

    return False unless $first + $second == $third;                           # [8]

    $first = $second;                                                         # [9]
    $second = $third;                                                         # [9b]
  }

  return True;                                                                # [11]
}

[1] A string of at least three characters, and we allow the digits 0 to 9 only. This applies to the main program as well as the wrapper procedure [1a].

[2] Call the procedure, and explicitly print "true" or "false" depending on the result.

[3] Split the string into a list of indvidual characters (or digits, in this case).

[4] Get the first digit (and remove it from the list).

[5] and the second one (also removed).

[6] As long as there are more digits in the list,

[7] Get the third digit.

[8] The third digit should be the sum of the first and second. Return False if it is not.

[9] Set up the first and second [9b] digits for the next iteration.

[10] Failure to falsify (in [8]) means success.

Running it:

$ ./additive-digit 112358
true

$ ./additive-digit 12345
false

$ ./additive-digit 199100199
false

The first two are correct, but the third one misses the mark as it does not handle multi-digit numbers. That is as expected.

Let us have a go at fixing that.

www.tutorialspoint.com has a nice walk through of a way of solving this. But what fun would it be to translate a bullet list of quasi code to Raku?

So I'll do it in a completely different way...

Let me start with the verbose output for a string that is an addative number (actually a modified version of the second example), and explain the approach:

$ ./additive-number -v 12315
:: 12315 -> 0000 -> '    ' -> 12315
:: 12315 -> 0001 -> '   |' -> 1231|5
:: 12315 -> 0010 -> '  | ' -> 123|15
:: 12315 -> 0011 -> '  ||' -> 123|1|5
:: 12315 -> 0100 -> ' |  ' -> 12|315
:: 12315 -> 0101 -> ' | |' -> 12|31|5
:: 12315 -> 0110 -> ' || ' -> 12|3|15
true

The first (verbose output) column is the string itself.

The second column is a zero padded binary number with size one less than the size of the string itself. We start at zero, and work our way upwards.

The third column is this number where the zeros are replaced with spaces, and the ones with a vertical bar (the | character).

The fourth and final column is the result of zipping (merging) the original string and the third column, with characters from alternate strings. The spaces has been removed.

After this we split the string in the final column on the vertical bar, giving us a list of numbers. We then check this list (if it has three or more elements) to see if it is addative, with a slighly modified version of the «is-additive» procedure.

File: additive-number
#! /usr/bin/env raku

unit sub MAIN ($string where $string.chars > 2 && $string ~~ /^<[0..9]>*$/,
  :v(:$verbose));

my $bitmap-length = $string.chars -1;                          # [1]

for 0 .. Inf -> $i                                             # [2]
{
  my $binary = $i.base(2);                                     # [3]

  last if $binary.chars > $bitmap-length;                      # [4]

  my $bitmap  = $binary.fmt('%0' ~ $bitmap-length ~ 'd');      # [5]
  my $bitmap2 = $bitmap;                                       # [6]

  $bitmap ~~ tr/01/ |/;                                        # [7]

  my @bitmap = $bitmap.comb;                                   # [8]
  my $new    = (roundrobin($string.comb, @bitmap)).flat.join;  # [9]
  $new ~~ s:g/\s//;                                            # [10]

  my @array = $new.split("|");                                 # [11]

  say ":: $string -> $bitmap2 -> '$bitmap' -> $new" if $verbose;

  next unless @array.elems >= 3;                               # [12]

  if is-additive(@array)                                       # [13]
  {
    say 'true';                                                # [13a]
    exit;                                                      # [13b]
  }
}

say 'false';                                                   # [14]

sub is-additive (@array)                                       # [15]
{
  my $first  = @array.shift;
  my $second = @array.shift;

  while (@array.elems)
  {
    my $third = @array.shift;

    return False unless $first + $second == $third;

    $first = $second;
    $second = $third;
  }

  return True;
}

[1] The length of the (binary) bitmap we are going to create.

[2] The easiest way of generating the bitmap is an infinite loop over decimal values, with a check on the lenght (in [4]).

[3] Convert the decimal value to binary with base(2).

See docs.raku.org/routine/base for more information about base.

[4] Exit the infinite loop if we have exceeded the required bitmap length.

[5] Stringify the bitmap with leading zeroes.

See docs.raku.org/routine/fmt for more information about fmt.

[6] Verbose mode requires this value later on.

[7] Get rid of spaces in the string with the s/// operator.

See https://docs.raku.org/language/operators#s///_in-place_substitution for more information about the in-place substitution operator s///.

[8] Get the bitmap as an array.

[9] Merge the original string with the bitmap with the zipper like function roundrobin. The result is a list of pair objects, with one value from each list (original string, bitmap), so we flatten this structure with flat, before we merge the resulting list into a single string with join.

See docs.raku.org/routine/roundrobin for more information about roundrobin.

[10] Get rid of spaces (from the bitmap).

[11] Split that string on the vertical bars to get a list of numbers.

[12] Skip this candidate if we have less than three values in the list.

Note that this could also have been done as e.g. next if $bitmap.comb.sum < 2; (counting the number of "1" digits), after [5].

[13] Is it additive? If so, print "true" and exit. (If not, go in in the loop.)

[14] None of the lists were additive, then it is not additive; print "false".

[15] A slightly modified version of the procedure, taking an array of numbers.

Running it:

$ ./additive-number 112358
true

$ ./additive-number 12345
false

$ ./additive-number 199100199
true

$ ./additive-number 12315
true

With verbose mode:

$ ./additive-number -v 112358
:: 112358 -> 00000 -> '     ' -> 112358
:: 112358 -> 00001 -> '    |' -> 11235|8
:: 112358 -> 00010 -> '   | ' -> 1123|58
:: 112358 -> 00011 -> '   ||' -> 1123|5|8
:: 112358 -> 00100 -> '  |  ' -> 112|358
:: 112358 -> 00101 -> '  | |' -> 112|35|8
:: 112358 -> 00110 -> '  || ' -> 112|3|58
:: 112358 -> 00111 -> '  |||' -> 112|3|5|8
:: 112358 -> 01000 -> ' |   ' -> 11|2358
:: 112358 -> 01001 -> ' |  |' -> 11|235|8
:: 112358 -> 01010 -> ' | | ' -> 11|23|58
:: 112358 -> 01011 -> ' | ||' -> 11|23|5|8
:: 112358 -> 01100 -> ' ||  ' -> 11|2|358
:: 112358 -> 01101 -> ' || |' -> 11|2|35|8
:: 112358 -> 01110 -> ' ||| ' -> 11|2|3|58
:: 112358 -> 01111 -> ' ||||' -> 11|2|3|5|8
:: 112358 -> 10000 -> '|    ' -> 1|12358
:: 112358 -> 10001 -> '|   |' -> 1|1235|8
:: 112358 -> 10010 -> '|  | ' -> 1|123|58
:: 112358 -> 10011 -> '|  ||' -> 1|123|5|8
:: 112358 -> 10100 -> '| |  ' -> 1|12|358
:: 112358 -> 10101 -> '| | |' -> 1|12|35|8
:: 112358 -> 10110 -> '| || ' -> 1|12|3|58
:: 112358 -> 10111 -> '| |||' -> 1|12|3|5|8
:: 112358 -> 11000 -> '||   ' -> 1|1|2358
:: 112358 -> 11001 -> '||  |' -> 1|1|235|8
:: 112358 -> 11010 -> '|| | ' -> 1|1|23|58
:: 112358 -> 11011 -> '|| ||' -> 1|1|23|5|8
:: 112358 -> 11100 -> '|||  ' -> 1|1|2|358
:: 112358 -> 11101 -> '||| |' -> 1|1|2|35|8
:: 112358 -> 11110 -> '|||| ' -> 1|1|2|3|58
:: 112358 -> 11111 -> '|||||' -> 1|1|2|3|5|8
true
$ ./additive-number -v 12345
:: 12345 -> 0000 -> '    ' -> 12345
:: 12345 -> 0001 -> '   |' -> 1234|5
:: 12345 -> 0010 -> '  | ' -> 123|45
:: 12345 -> 0011 -> '  ||' -> 123|4|5
:: 12345 -> 0100 -> ' |  ' -> 12|345
:: 12345 -> 0101 -> ' | |' -> 12|34|5
:: 12345 -> 0110 -> ' || ' -> 12|3|45
:: 12345 -> 0111 -> ' |||' -> 12|3|4|5
:: 12345 -> 1000 -> '|   ' -> 1|2345
:: 12345 -> 1001 -> '|  |' -> 1|234|5
:: 12345 -> 1010 -> '| | ' -> 1|23|45
:: 12345 -> 1011 -> '| ||' -> 1|23|4|5
:: 12345 -> 1100 -> '||  ' -> 1|2|345
:: 12345 -> 1101 -> '|| |' -> 1|2|34|5
:: 12345 -> 1110 -> '||| ' -> 1|2|3|45
:: 12345 -> 1111 -> '||||' -> 1|2|3|4|5
false
$ ./additive-number -v 199100199
:: 199100199 -> 00000000 -> '        ' -> 199100199
:: 199100199 -> 00000001 -> '       |' -> 19910019|9
:: 199100199 -> 00000010 -> '      | ' -> 1991001|99
:: 199100199 -> 00000011 -> '      ||' -> 1991001|9|9
:: 199100199 -> 00000100 -> '     |  ' -> 199100|199
:: 199100199 -> 00000101 -> '     | |' -> 199100|19|9
:: 199100199 -> 00000110 -> '     || ' -> 199100|1|99
:: 199100199 -> 00000111 -> '     |||' -> 199100|1|9|9
:: 199100199 -> 00001000 -> '    |   ' -> 19910|0199
:: 199100199 -> 00001001 -> '    |  |' -> 19910|019|9
:: 199100199 -> 00001010 -> '    | | ' -> 19910|01|99
:: 199100199 -> 00001011 -> '    | ||' -> 19910|01|9|9
:: 199100199 -> 00001100 -> '    ||  ' -> 19910|0|199
:: 199100199 -> 00001101 -> '    || |' -> 19910|0|19|9
:: 199100199 -> 00001110 -> '    ||| ' -> 19910|0|1|99
:: 199100199 -> 00001111 -> '    ||||' -> 19910|0|1|9|9
:: 199100199 -> 00010000 -> '   |    ' -> 1991|00199
:: 199100199 -> 00010001 -> '   |   |' -> 1991|0019|9
:: 199100199 -> 00010010 -> '   |  | ' -> 1991|001|99
:: 199100199 -> 00010011 -> '   |  ||' -> 1991|001|9|9
:: 199100199 -> 00010100 -> '   | |  ' -> 1991|00|199
:: 199100199 -> 00010101 -> '   | | |' -> 1991|00|19|9
:: 199100199 -> 00010110 -> '   | || ' -> 1991|00|1|99
:: 199100199 -> 00010111 -> '   | |||' -> 1991|00|1|9|9
:: 199100199 -> 00011000 -> '   ||   ' -> 1991|0|0199
:: 199100199 -> 00011001 -> '   ||  |' -> 1991|0|019|9
:: 199100199 -> 00011010 -> '   || | ' -> 1991|0|01|99
:: 199100199 -> 00011011 -> '   || ||' -> 1991|0|01|9|9
:: 199100199 -> 00011100 -> '   |||  ' -> 1991|0|0|199
:: 199100199 -> 00011101 -> '   ||| |' -> 1991|0|0|19|9
:: 199100199 -> 00011110 -> '   |||| ' -> 1991|0|0|1|99
:: 199100199 -> 00011111 -> '   |||||' -> 1991|0|0|1|9|9
:: 199100199 -> 00100000 -> '  |     ' -> 199|100199
:: 199100199 -> 00100001 -> '  |    |' -> 199|10019|9
:: 199100199 -> 00100010 -> '  |   | ' -> 199|1001|99
:: 199100199 -> 00100011 -> '  |   ||' -> 199|1001|9|9
:: 199100199 -> 00100100 -> '  |  |  ' -> 199|100|199
:: 199100199 -> 00100101 -> '  |  | |' -> 199|100|19|9
:: 199100199 -> 00100110 -> '  |  || ' -> 199|100|1|99
:: 199100199 -> 00100111 -> '  |  |||' -> 199|100|1|9|9
:: 199100199 -> 00101000 -> '  | |   ' -> 199|10|0199
:: 199100199 -> 00101001 -> '  | |  |' -> 199|10|019|9
:: 199100199 -> 00101010 -> '  | | | ' -> 199|10|01|99
:: 199100199 -> 00101011 -> '  | | ||' -> 199|10|01|9|9
:: 199100199 -> 00101100 -> '  | ||  ' -> 199|10|0|199
:: 199100199 -> 00101101 -> '  | || |' -> 199|10|0|19|9
:: 199100199 -> 00101110 -> '  | ||| ' -> 199|10|0|1|99
:: 199100199 -> 00101111 -> '  | ||||' -> 199|10|0|1|9|9
:: 199100199 -> 00110000 -> '  ||    ' -> 199|1|00199
:: 199100199 -> 00110001 -> '  ||   |' -> 199|1|0019|9
:: 199100199 -> 00110010 -> '  ||  | ' -> 199|1|001|99
:: 199100199 -> 00110011 -> '  ||  ||' -> 199|1|001|9|9
:: 199100199 -> 00110100 -> '  || |  ' -> 199|1|00|199
:: 199100199 -> 00110101 -> '  || | |' -> 199|1|00|19|9
:: 199100199 -> 00110110 -> '  || || ' -> 199|1|00|1|99
:: 199100199 -> 00110111 -> '  || |||' -> 199|1|00|1|9|9
:: 199100199 -> 00111000 -> '  |||   ' -> 199|1|0|0199
:: 199100199 -> 00111001 -> '  |||  |' -> 199|1|0|019|9
:: 199100199 -> 00111010 -> '  ||| | ' -> 199|1|0|01|99
:: 199100199 -> 00111011 -> '  ||| ||' -> 199|1|0|01|9|9
:: 199100199 -> 00111100 -> '  ||||  ' -> 199|1|0|0|199
:: 199100199 -> 00111101 -> '  |||| |' -> 199|1|0|0|19|9
:: 199100199 -> 00111110 -> '  ||||| ' -> 199|1|0|0|1|99
:: 199100199 -> 00111111 -> '  ||||||' -> 199|1|0|0|1|9|9
:: 199100199 -> 01000000 -> ' |      ' -> 19|9100199
:: 199100199 -> 01000001 -> ' |     |' -> 19|910019|9
:: 199100199 -> 01000010 -> ' |    | ' -> 19|91001|99
:: 199100199 -> 01000011 -> ' |    ||' -> 19|91001|9|9
:: 199100199 -> 01000100 -> ' |   |  ' -> 19|9100|199
:: 199100199 -> 01000101 -> ' |   | |' -> 19|9100|19|9
:: 199100199 -> 01000110 -> ' |   || ' -> 19|9100|1|99
:: 199100199 -> 01000111 -> ' |   |||' -> 19|9100|1|9|9
:: 199100199 -> 01001000 -> ' |  |   ' -> 19|910|0199
:: 199100199 -> 01001001 -> ' |  |  |' -> 19|910|019|9
:: 199100199 -> 01001010 -> ' |  | | ' -> 19|910|01|99
:: 199100199 -> 01001011 -> ' |  | ||' -> 19|910|01|9|9
:: 199100199 -> 01001100 -> ' |  ||  ' -> 19|910|0|199
:: 199100199 -> 01001101 -> ' |  || |' -> 19|910|0|19|9
:: 199100199 -> 01001110 -> ' |  ||| ' -> 19|910|0|1|99
:: 199100199 -> 01001111 -> ' |  ||||' -> 19|910|0|1|9|9
:: 199100199 -> 01010000 -> ' | |    ' -> 19|91|00199
:: 199100199 -> 01010001 -> ' | |   |' -> 19|91|0019|9
:: 199100199 -> 01010010 -> ' | |  | ' -> 19|91|001|99
:: 199100199 -> 01010011 -> ' | |  ||' -> 19|91|001|9|9
:: 199100199 -> 01010100 -> ' | | |  ' -> 19|91|00|199
:: 199100199 -> 01010101 -> ' | | | |' -> 19|91|00|19|9
:: 199100199 -> 01010110 -> ' | | || ' -> 19|91|00|1|99
:: 199100199 -> 01010111 -> ' | | |||' -> 19|91|00|1|9|9
:: 199100199 -> 01011000 -> ' | ||   ' -> 19|91|0|0199
:: 199100199 -> 01011001 -> ' | ||  |' -> 19|91|0|019|9
:: 199100199 -> 01011010 -> ' | || | ' -> 19|91|0|01|99
:: 199100199 -> 01011011 -> ' | || ||' -> 19|91|0|01|9|9
:: 199100199 -> 01011100 -> ' | |||  ' -> 19|91|0|0|199
:: 199100199 -> 01011101 -> ' | ||| |' -> 19|91|0|0|19|9
:: 199100199 -> 01011110 -> ' | |||| ' -> 19|91|0|0|1|99
:: 199100199 -> 01011111 -> ' | |||||' -> 19|91|0|0|1|9|9
:: 199100199 -> 01100000 -> ' ||     ' -> 19|9|100199
:: 199100199 -> 01100001 -> ' ||    |' -> 19|9|10019|9
:: 199100199 -> 01100010 -> ' ||   | ' -> 19|9|1001|99
:: 199100199 -> 01100011 -> ' ||   ||' -> 19|9|1001|9|9
:: 199100199 -> 01100100 -> ' ||  |  ' -> 19|9|100|199
:: 199100199 -> 01100101 -> ' ||  | |' -> 19|9|100|19|9
:: 199100199 -> 01100110 -> ' ||  || ' -> 19|9|100|1|99
:: 199100199 -> 01100111 -> ' ||  |||' -> 19|9|100|1|9|9
:: 199100199 -> 01101000 -> ' || |   ' -> 19|9|10|0199
:: 199100199 -> 01101001 -> ' || |  |' -> 19|9|10|019|9
:: 199100199 -> 01101010 -> ' || | | ' -> 19|9|10|01|99
:: 199100199 -> 01101011 -> ' || | ||' -> 19|9|10|01|9|9
:: 199100199 -> 01101100 -> ' || ||  ' -> 19|9|10|0|199
:: 199100199 -> 01101101 -> ' || || |' -> 19|9|10|0|19|9
:: 199100199 -> 01101110 -> ' || ||| ' -> 19|9|10|0|1|99
:: 199100199 -> 01101111 -> ' || ||||' -> 19|9|10|0|1|9|9
:: 199100199 -> 01110000 -> ' |||    ' -> 19|9|1|00199
:: 199100199 -> 01110001 -> ' |||   |' -> 19|9|1|0019|9
:: 199100199 -> 01110010 -> ' |||  | ' -> 19|9|1|001|99
:: 199100199 -> 01110011 -> ' |||  ||' -> 19|9|1|001|9|9
:: 199100199 -> 01110100 -> ' ||| |  ' -> 19|9|1|00|199
:: 199100199 -> 01110101 -> ' ||| | |' -> 19|9|1|00|19|9
:: 199100199 -> 01110110 -> ' ||| || ' -> 19|9|1|00|1|99
:: 199100199 -> 01110111 -> ' ||| |||' -> 19|9|1|00|1|9|9
:: 199100199 -> 01111000 -> ' ||||   ' -> 19|9|1|0|0199
:: 199100199 -> 01111001 -> ' ||||  |' -> 19|9|1|0|019|9
:: 199100199 -> 01111010 -> ' |||| | ' -> 19|9|1|0|01|99
:: 199100199 -> 01111011 -> ' |||| ||' -> 19|9|1|0|01|9|9
:: 199100199 -> 01111100 -> ' |||||  ' -> 19|9|1|0|0|199
:: 199100199 -> 01111101 -> ' ||||| |' -> 19|9|1|0|0|19|9
:: 199100199 -> 01111110 -> ' |||||| ' -> 19|9|1|0|0|1|99
:: 199100199 -> 01111111 -> ' |||||||' -> 19|9|1|0|0|1|9|9
:: 199100199 -> 10000000 -> '|       ' -> 1|99100199
:: 199100199 -> 10000001 -> '|      |' -> 1|9910019|9
:: 199100199 -> 10000010 -> '|     | ' -> 1|991001|99
:: 199100199 -> 10000011 -> '|     ||' -> 1|991001|9|9
:: 199100199 -> 10000100 -> '|    |  ' -> 1|99100|199
:: 199100199 -> 10000101 -> '|    | |' -> 1|99100|19|9
:: 199100199 -> 10000110 -> '|    || ' -> 1|99100|1|99
:: 199100199 -> 10000111 -> '|    |||' -> 1|99100|1|9|9
:: 199100199 -> 10001000 -> '|   |   ' -> 1|9910|0199
:: 199100199 -> 10001001 -> '|   |  |' -> 1|9910|019|9
:: 199100199 -> 10001010 -> '|   | | ' -> 1|9910|01|99
:: 199100199 -> 10001011 -> '|   | ||' -> 1|9910|01|9|9
:: 199100199 -> 10001100 -> '|   ||  ' -> 1|9910|0|199
:: 199100199 -> 10001101 -> '|   || |' -> 1|9910|0|19|9
:: 199100199 -> 10001110 -> '|   ||| ' -> 1|9910|0|1|99
:: 199100199 -> 10001111 -> '|   ||||' -> 1|9910|0|1|9|9
:: 199100199 -> 10010000 -> '|  |    ' -> 1|991|00199
:: 199100199 -> 10010001 -> '|  |   |' -> 1|991|0019|9
:: 199100199 -> 10010010 -> '|  |  | ' -> 1|991|001|99
:: 199100199 -> 10010011 -> '|  |  ||' -> 1|991|001|9|9
:: 199100199 -> 10010100 -> '|  | |  ' -> 1|991|00|199
:: 199100199 -> 10010101 -> '|  | | |' -> 1|991|00|19|9
:: 199100199 -> 10010110 -> '|  | || ' -> 1|991|00|1|99
:: 199100199 -> 10010111 -> '|  | |||' -> 1|991|00|1|9|9
:: 199100199 -> 10011000 -> '|  ||   ' -> 1|991|0|0199
:: 199100199 -> 10011001 -> '|  ||  |' -> 1|991|0|019|9
:: 199100199 -> 10011010 -> '|  || | ' -> 1|991|0|01|99
:: 199100199 -> 10011011 -> '|  || ||' -> 1|991|0|01|9|9
:: 199100199 -> 10011100 -> '|  |||  ' -> 1|991|0|0|199
:: 199100199 -> 10011101 -> '|  ||| |' -> 1|991|0|0|19|9
:: 199100199 -> 10011110 -> '|  |||| ' -> 1|991|0|0|1|99
:: 199100199 -> 10011111 -> '|  |||||' -> 1|991|0|0|1|9|9
:: 199100199 -> 10100000 -> '| |     ' -> 1|99|100199
:: 199100199 -> 10100001 -> '| |    |' -> 1|99|10019|9
:: 199100199 -> 10100010 -> '| |   | ' -> 1|99|1001|99
:: 199100199 -> 10100011 -> '| |   ||' -> 1|99|1001|9|9
:: 199100199 -> 10100100 -> '| |  |  ' -> 1|99|100|199
true

Quite a lot of verbose output for this one. That is why I came up with the example string «12315» for the initial explanation.

The verbose output above should give a hint that this brute force approach is not very efficient, especially if the length of the input string is large.

$ ./additive-number -v 12315
:: 12315 -> 0000 -> '    ' -> 12315
:: 12315 -> 0001 -> '   |' -> 1231|5
:: 12315 -> 0010 -> '  | ' -> 123|15
:: 12315 -> 0011 -> '  ||' -> 123|1|5
:: 12315 -> 0100 -> ' |  ' -> 12|315
:: 12315 -> 0101 -> ' | |' -> 12|31|5
:: 12315 -> 0110 -> ' || ' -> 12|3|15
true

Note that we could get rid of arrays with numbers with more than one digit, and the first one is a zero. This would fit in between [12] and [13]. But the check would require some work (and code), and it may not be worth the effort.

Note that we could also get rid of arrays where the number of digits in any element is smaller than the highest of the two elements to the left of it (as it should be the sum of those values).

And that's it.