17 January 2023

Slicing and dicing a double century

 

200/1 = Arithmetic slices

You are given an array of integers, @array. Write a script to find out all Arithmetic Slices for the given array of integers. An integer array is called arithmetic if it has at least 3 elements and the differences between any three consecutive elements are the same.

Example:
Input: @array = (1,2,3,4)
Output: (1,2,3), (2,3,4), (1,2,3,4)

For ease, I decided to start by creating an array @diff, where $diff[$j] = $array[$j + 1] - $array[$j] - so I am looking for runs of 3 or more identical numbers in @diff. 

I move along @diff, maintaining a value $run_starts which is the index into @array where the current run of identical values of $diff[$j] starts, and $this_diff which is that value. Whenever I reach a $j which is not equal to $this_diff I know that $array[$j] is the end of the current run and potentially the start of another run.

Having identified a run of identical values of $diff[$j]:

  • if it is less than 3 long I ignore it
  • if it is 3 long, then I add it to the output
  • if it is more than 3 long I add all its subsets as well - as in the example above
For convenience and clarity I have delegated that part of the task to subroutine &analyse.

In my submission I have added a number of edge cases, such as zero or negative numbers in @array, runs of negative differences, overlapping slices (eg 1, 2, 3, 6, 9).

200/2 = Seven segment 200

A seven segment display is an electronic component used to display digits. The segments are labelled 'a' through 'g' as shown:

The encoding of each digit can thus be represented compactly as a truth table:

my @truth =
    qw<abcdef bc abdeg abcdg bcfg acdfg acdefg abc abcdefg abcfg>;

For example, $truth[1] = ‘bc’. The digit 1 would have segments ‘b’ and ‘c’ enabled.

Write a program that accepts any decimal number and draws that number as a horizontal sequence of ASCII seven segment displays, similar to the following:

Given a digit to display, the truth table tells us which segments to 'light up', for example 'abdeg' for 2. We need to start with a blank 7x7 matrix and populate the appropriate positions with a symbol - either | or -. I decided to do that using another lookup table, which I created like this:

$digit[ord('a')] = '-00 -01 -02 -03 -04 -05 -06';
$digit[ord('b')] = '|16 |26';
$digit[ord('c')] = '|46 |56';
$digit[ord('d')] = '-60 -61 -62 -63 -64 -65 -66';
$digit[ord('e')] = '|40 |50';
$digit[ord('f')] = '|10 |20';
$digit[ord('g')] = '-30 -31 -32 -33 -34 -35 -36';

For each letter, a to g, I can then determine the symbol and the positions needed, for example 'a' needs a '-' in row 0, column 0; in row 0 column 1 and so on.

I build up the display in an 2-dimensional array @display, which is 7 rows high and 9n characters wide, where n is the number of digits to be displayed (9 rather than 7 to allow two blanks between successive digits). And this is how I do it:

$segments = $truth[$1];
while ($segments =~ m|(.)|g) {
    $points = $digit[ord($1)];
    while ($points =~ m|(.)(\d)(\d)|g) {
        $display[$2][$3 + $offset] = $1;
    }
}

Then it's just a case of printing @display with a \n after each row.

My solution





No comments:

Post a Comment