N Binary
with Raku

by Arne Sommer

N Binary with Raku

[409] Published 1. August 2026.

This is my response to The Weekly Challenge #384.

#384.1 Base N You are given a number and a base integer.

Write a script to convert the given number in the given base integer.

Example 1:
Input: $num = 42, $base = 2
Output: 101010
Example 2:
Input: $num = 15642094, $base = 16
Output: EEADEE
Example 3:
Input: $num = 493, $base = 8
Output: 755
Example 4:
Input: $num = 2228519, $base = 36
Output: 1BRJB

Base 36 uses numbers 0-9 and letters A-Z.
Example 5:
Input: $num = 123456789, $base = 64
Output: 7MyqL

Base 64 (using 0-9, A-Z, a-z, and extra symbols like + and /)
File: base-n
#! /usr/bin/env raku

multi sub MAIN (Int :n(:$num), 
                Int :b(:$base) where $base == 1,
		    :v(:$verbose))
{
  say ( '0' x $num );
}

multi sub MAIN (Int :n(:$num),
                Int :b(:$base) where 2 <= $base <= 16,
		    :v(:$verbose))
{
  say $num.base($base);
}

multi sub MAIN (Int :n(:$num) is copy,
                Int :b(:$base) where 17 <= $base <= 64,
		    :v(:$verbose))
{
  my $result = "";

  while $num
  {
    my $digit   = $num % $base;
    my $new     = $num div $base;

    my $in-base = do given $digit
    {
      when *  < 10 { $digit }
      when *  < 36 { ($digit - 10 + 'A'.ord).chr }
      when *  < 62 { ($digit - 36 + 'a'.ord).chr }
      when * == 62 { "+" }
      when * == 63 { "/" }
    }

    say ": $num / $base = $new + $digit -> $in-base"
      if $verbose;

    $result ~= $in-base;

    $num = $new;
  }

  say $result.flip;
}

I have chosen multiple dispatch (with multi) for this one, as the bases can be grouped in three.

[3] Base 1 is easy, but not really a positional number system, so perhaps should be considered illegal by the program.

[7] Print as many zeroes as the value of the base. The actual symbol is irrelevant, but zero fits in with the general pattern; base 2 (0,1), base 3 (0,1,2), and so on. Note that the number zero is represented as en empty string, which really makes this a peculiar number system...

[10] Base 2 to 16 are easy, as we can use the

[14] built-in base function.

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

[16] Base 17 to 64 must be dealt with manually. (I have not checked if there is a Raku module for this.)

[21] The resulting string will end up here, backwards.

[23] As long as we have not reduced the input value to zero.

[25] Get the new digit (in decimal, so may actually be several digits) with the modulo operator %.

[26] Get the new input variable.

[28] Convert the digit to the given base with given/when. The do part collapses the given block (pun intended) so that we can assign it like this.

See docs.raku.org/syntax/default when for more information about given/when/default.

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

[39] Add the new digit to the result.

[41] Update the input variable.

[44] Print he result, but reversed (with flip), as the loop gave us the digits in wrong order.

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

Running it:

$ ./base-n -n=42 -b=2
101010

$ ./base-n -n=15642094 -b=16
EEADEE

$ ./base-n -n=493 -b=8
755

$ ./base-n -n=2228519 -b=36
1BRJB

$ ./base-n -n=123456789 -b=64
7MyqL

Looking good.

With verbose mode (which is only implemented for bases 17 to 64):

$ ./base-n -v -n=42 -b=2
101010

$ ./base-n -v -n=15642094 -b=16
EEADEE

$ ./base-n -v -n=493 -b=8
755

$ ./base-n -v -n=2228519 -b=36
: 2228519 / 36 = 61903 + 11 -> B
: 61903 / 36 = 1719 + 19 -> J
: 1719 / 36 = 47 + 27 -> R
: 47 / 36 = 1 + 11 -> B
: 1 / 36 = 0 + 1 -> 1
1BRJB

$ ./base-n -v -n=123456789 -b=64
: 123456789 / 64 = 1929012 + 21 -> L
: 1929012 / 64 = 30140 + 52 -> q
: 30140 / 64 = 470 + 60 -> y
: 470 / 64 = 7 + 22 -> M
: 7 / 64 = 0 + 7 -> 7
7MyqL

#384.2 Special Binary Substrings You are given a binary string.

Write a script to return all non-empty substrings (distinct) that have the same number of 0’s and 1’s, and all the 0’s and all the 1’s in these substrings are grouped consecutively.

Example 1:
Input: $binary = "0101"
Output: ("01", "10")
Example 2:
Input: $binary = "000111"
Output: ("000111", "0011", "01")
Example 3:
Input: $binary = "000011"
Output:  ("0011", "01")
Example 4:
Input: $binary = "10011100"
Output: ("10", "0011", "01", "1100")
Example 5:
Input: $binary = "00000"
Output: ()
File: special-binary-substring
#! /usr/bin/env raku

subset BINARY where /^ <[01]>+ $ /;

unit sub MAIN (BINARY $binary, :v(:$verbose));

my @ok;

for 0 .. $binary.chars - 2 -> $i
{
  for $i + 1 .. $binary.chars - 1 -> $j
  {
    my $candidate = $binary.substr($i, $j - $i +1);

    next unless $candidate.chars %% 2;
    next unless $candidate.comb.sum == $candidate.chars / 2;
    next unless $candidate ~~ /^ (0+ 1+ | 1+ 0+) $/;

    say ":$binary" ~ "[$i .. $j] -> $candidate" if $verbose;

    @ok.push: $candidate;
  }
}

say "({ @ok.unique.map( '"' ~ * ~ '"' ).join(", ") })";

[3] A custom type with subset, to be used in [5].

See docs.raku.org/language/typesystem#subset for more information about subset.

[5] Ensure a binary number, with at least one digit.

[7] The special binary substrings will end up here.

[9] Iterate over all possible starting indices,

[11] and ending indices. Note that the minimum substring length is 2.

[13] Get the actual substring.

[15] Skip substrings that does not have an even length.

[16] Skip substrings where the number of 0s and 1s are the same.

[17] Skip substring where the digits are not sorted in two groups.

[21] We have a candidate, add it to the result.

[25] Get rid of duplicates (the "(distinct)" clause in the challenge), if any, with unique and pretty print the result.

Running it:

$ ./special-binary-substring 0101
("01", "10", "01")

$ ./special-binary-substring 000111
("000111", "0011", "01")

$ ./special-binary-substring 000011
("0011", "01")

$ ./special-binary-substring 10011100
("10", "0011", "01", "1100")

$ ./special-binary-substring -v 00000
()

Looking good.

With verbose mode:

$ ./special-binary-substring -v 0101
:0101[0 .. 1] -> 01
:0101[1 .. 2] -> 10
:0101[2 .. 3] -> 01
("01", "10", "01")

)$ ./special-binary-substring -v 000111
:000111[0 .. 5] -> 000111
:000111[1 .. 4] -> 0011
:000111[2 .. 3] -> 01
("000111", "0011", "01")

$ ./special-binary-substring -v 000011
:000011[2 .. 5] -> 0011
:000011[3 .. 4] -> 01
("0011", "01")

$ ./special-binary-substring -v 10011100
:10011100[0 .. 1] -> 10
:10011100[1 .. 4] -> 0011
:10011100[2 .. 3] -> 01
:10011100[4 .. 7] -> 1100
:10011100[5 .. 6] -> 10
("10", "0011", "01", "1100")

$ ./special-binary-substring -v 00000
()

The fourth example has a duplicate value (10), as shown above, but the unique method (in [25]) got rid of it for us.

And that's it.