aboutsummaryrefslogtreecommitdiff
path: root/challenge-204/james-smith/README.md
blob: d72e1d0ee20b7af502c561451e6394dadb0b505b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
[< Previous 203](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-203/james-smith) |
[Next 205 >](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-205/james-smith)

# The Weekly Challenge 204

You can find more information about this weeks, and previous weeks challenges at:

  https://theweeklychallenge.org/

If you are not already doing the challenge - it is a good place to practise your
**perl** or **raku**. If it is not **perl** or **raku** you develop in - you can
submit solutions in whichever language you feel comfortable with.

You can find the solutions here on github at:

https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-204/james-smith

# Task 1: Monotonic Array

***You are given an array of integers. Write a script to find out if the given array is Monotonic. Print 1 if it is otherwise 0. An array is Monotonic if it is either monotone increasing or decreasing.***

## Solution

We loop through the array - firstly trying to find if the string is increasing or decreasing.

To do so we collect ths sign of the difference between successive numbers UNTIL we find a non-zero value..

We then see if all subsequence differences have the same sign (or 0)....

```perl
sub monotonic {
  my($p,$d,$t)=$_[0];
  ($t=$p<=>$_)&&($d||=$t)!=$t?(return 0):($p=$_)for@_;
  1
}
```

```perl
sub monotonic {
  my($p,$d,$t)=($_[0],0);
     ($t=$p<=>$_)        ## Get next signum of the pairwise difference (and store in $t) 
  && ($d||=$t) != $t     ## If this new difference is non-zero
                         ##   we update the direction [IF it is previously non-zero]
                         ##   and compare it against the value we have just computed
   ? (return 0)          ## If the difference is different we return 0
   : ($p=$_)             ## Otherwise we update the previous value...
   for @_;               ## and repeat for all values.
  1;                     ## We have no differences!
}
```

# Task 2: Reshape Matrix

***You are given a matrix (m x n) and two integers (r) and (c). Write a script to reshape the given matrix in form (r x c) with the original value in the given matrix. If you can’t reshape print 0.***

Our first pass - is simple - we first do a dimension check to see if the matrix is the right size. Then we stitch all the rows together into a single list, and chomp off line-by-line.

```perl
sub reshape {
  my($m,$r,$c) = @_;
  return 0 unless @{$m}*@{$m->[0]} == $r * $c;
  my @t = map { @{$_} } @{$m};
  [ map { [ splice @t, 0, $c ] } 1..$r ];
}
```

Our second pass is a bit more complicated as we try and avoid the stitch everything together in a long line...

 * Here we start again with the size check then we construct each row of the target array, chunk by chunk,
 * We find the part of the of the first row of the source which will fit in the target row.
    * If we reach the end of the target row - we push this to our target matrix
    * If it does not we repeat again adding bits of the 2nd, 3rd,... rows of the source to the target.
 * We repeat for all rows - noting that we may NOT start at the beginning of a source row - but at `$x` are cursor position.

This method is more efficient memory wise - a consideration if you are reshaping a large matrix.

```perl
sub reshape2 {
  my($m,$r,$c) = @_;
  my $R=@{$m}; my $C = @{$m->[0]};
  return 0 unless (my $R=@{$m}) * (my $C=@{$m->[0]}) == $r * $c;
  my($x,$y,$res)=(0,0);
  for my $i (1..$r) {
    my $row = [];
    my $to_push = $c;
    while( $to_push ) {
      my $t = $to_push+$x<$C?$to_push+$x:$C;
      push @{$row},@{$m->[$y]}[$x..$t-1];
      $to_push -= $t-$x;
      $t==$C ? ($y++,$x=0) : ($x=$t);
    }
    push @{$res},$row;
  }
  $res
}
```