54
\$\begingroup\$

PPCG user and elected mod, @Dennis just became the second ever user to earn over 100k rep!

enter image description here

This is a totally original idea, that I did not get from anybody else, but let's make a challenge based off of his user ID, 12012 as a tribute!

Looking at it, you'll notice that there are two distinct "sections" to his ID.

12

and

012

Both of these sections add up to a 3. That's a pretty interesting property.

Let's define a "Dennis 2.0 number" as any positive integer where every maximal subsequence of strictly increasing digits sums to the same number. For example,

123

is a Dennis 2.0 number because there is only one maximal sublist of strictly increasing digits, and it sums to 6. Additionally, 2,846,145 is also a Dennis 2.0 number because the three maximal sublists of increasing digits, namely

28
46
145

All sum to 10. Additionally, numbers that just repeat the same digit must be Dennis 2.0 numbers because, for example, 777 can be broken down into

7
7
7

which clearly all sum to seven.

A number such as 42 is not a Dennis 2.0 number, since it is broken down into

4
2

which clearly do not sum to the same number.

The challenge

You must write a program or function to determine if a given number is a Dennis 2.0 number or not. You can take input and output in any reasonable input format, e.g. as a string, as a number, from a file, funtion arguments/return, from STDIN/STDOUT, etc. and then return a truthy value if this number is a Dennis 2.0 number, and a falsy value if it is not. For reference, here is every Dennis 2.0 number up to 1,000:

1
2
3
4
5
6
7
8
9
11
12
13
14
15
16
17
18
19
22
23
24
25
26
27
28
29
33
34
35
36
37
38
39
44
45
46
47
48
49
55
56
57
58
59
66
67
68
69
77
78
79
88
89
99
101
111
123
124
125
126
127
128
129
134
135
136
137
138
139
145
146
147
148
149
156
157
158
159
167
168
169
178
179
189
202
222
234
235
236
237
238
239
245
246
247
248
249
256
257
258
259
267
268
269
278
279
289
303
312
333
345
346
347
348
349
356
357
358
359
367
368
369
378
379
389
404
413
444
456
457
458
459
467
468
469
478
479
489
505
514
523
555
567
568
569
578
579
589
606
615
624
666
678
679
689
707
716
725
734
777
789
808
817
826
835
888
909
918
927
936
945
999

Standard loopholes apply, and the shortest answer measured in bytes wins!

\$\endgroup\$
  • 1
    \$\begingroup\$ Just for reference, Martin Ender was the first one to ever get 100k rep. \$\endgroup\$ – Erik the Outgolfer Sep 30 '16 at 15:48
  • 1
    \$\begingroup\$ Is 12366 a valid 2.0 number? (123|6|6 vs. 1236|6) \$\endgroup\$ – Sp3000 Sep 30 '16 at 16:00
  • 2
    \$\begingroup\$ @sp3000 That is not a Dennis number. It would be 1236|6 \$\endgroup\$ – DJMcMayhem Sep 30 '16 at 16:03
  • \$\begingroup\$ Can I take each digit as it's unary representation with a , between them? This is probably stretching it a lot. \$\endgroup\$ – Riley Sep 30 '16 at 16:16
  • 13
    \$\begingroup\$ Im scared Dennis will destroy all of us in this challenge nontheless \$\endgroup\$ – downrep_nation Sep 30 '16 at 17:14

22 Answers 22

15
\$\begingroup\$

Jelly, 13 12 bytes

1 byte thanks to @Dennis.

DIṠ’0;œṗDS€E

Try it online!

Explanation

DIṠ’0;œṗDS€E    Main link. Argument: N
D               Convert N to its digits.
 I              Find the differences between the elements.
  Ṡ             Find the sign of each difference. This yields 1 for locations where the
                list is strictly increasing and 0 or -1 elsewhere.
   ’            Decrement. This yields 0 for locations where the list is strictly
                increasing and -1 or -2 elsewhere.
    0;          Prepend a 0.
        D       Get another list of digits.
      œṗ        Split the list of digits at truthy positions, i.e. the -1s and -2s.
         S€     Sum each sublist.
           E    Check if all values are equal.
\$\endgroup\$
16
\$\begingroup\$

JavaScript (ES6), 72 70 bytes

Takes a string as input. Returns either false or a truthy value (which can be a number).

It's using a regular expression to transform an input string such as "2846145" into:

"(a=2+8)&&(a==4+6)&&(a==1+4+5)"

Then calls eval() on this expression.

let f =

n=>eval(n.replace(/./g,(v,i)=>(v>n[i-1]?'+':i?')&&(a==':'(a=')+v)+')')

console.log(f("101"));
console.log(f("102"));
console.log(f("777"));
console.log(f("2846145"));

\$\endgroup\$
  • \$\begingroup\$ Nice, that's a really smart idea. :-) \$\endgroup\$ – ETHproductions Sep 30 '16 at 17:06
  • \$\begingroup\$ Like that idea as well! But this is not working: console.log(f("2011")); // false console.log(f("189")); // 18 \$\endgroup\$ – user470370 Oct 3 '16 at 16:48
  • 3
    \$\begingroup\$ @user470370 - I think that's actually correct. The definition states "subsequences of strictly increasing numbers", so 2011 splits as 2 / 01 / 1 and is not a D2.0 number. As for 189, it is a D2.0 number and 18 is a truthy value. \$\endgroup\$ – Arnauld Oct 3 '16 at 17:09
  • \$\begingroup\$ Ups 😳 Of course, you are right. Didn't get that before. I think, I have to rework my own solution :D \$\endgroup\$ – user470370 Oct 3 '16 at 18:23
15
\$\begingroup\$

Python, 50 bytes

r='0'
for d in input():r=d+'=+'[r<d]*2+r
1/eval(r)

Expects input() to evaluate to a string, so the input needs surrounding quotes in Python 2. Output is via exit code, where 0 indicates success (truthy) and 1 indicates failure (falsy).

Test it on Ideone.

How it works

We initialize r to the string 0 and iterate over all digits d in the input.

  • If d is larger than the first digit of r (initially 0, then equal to the previous value of d), r<d evaluates to True and '=+'[r<d]*2 yields ++.

  • If d is smaller than the first digit of r, '=+'[r<d]*2 yields ==.

  • If d is equal to the first digit of r, r will be longer than the singleton string d, so '=+'[r<d]*2 yields once again ==.

In all cases, the digit d and the two generated characters get prepended to r.

Once all input digits have been processed, eval(r) evaluates the generated expression.

  • If the input consists of a single strictly increasing sequence of (positive) digits, the expression evaluates to their sum.

    For example, the integer 12345 results in the expression 5++4++3++2++1++0, which yields 15 when evaluated. Note that each second + is a unary plus, so it doesn't affect the result. Dividing 1 by 15 is valid (the result is not important); the program exits normally.

  • If the input consists of two strictly increasing sequences of digits, the expression consists of a simple comparison.

    For example, the integer 12012 results in the expression 2++1++0==2++1++0, which yields True when evaluated since both terms have sum 3. Dividing 1 by True (1) is valid (the result is not important); the program exits normally.

    On the other hand, the integer 12366 results in the expression 6==6++3++2++1++0, which yields False when evaluated since the terms have sums 6 and 12. Dividing 1 by False (0) raises a ZeroDivisionError; the program exits with an error.

  • If the input consists of three or more strictly increasing sequences of digits, the expression consists of a chained comparison, which returns True if and only if all involved comparisons return True.

    For example, the integer 94536 results in the expression 6++3==5++4==9++0, which yields True when evaluated since all terms have sum 9. As before, the program exits normally.

    On the other hand, the integer 17263 results in the expression 3==6++2==7++1++0, which yields False when evaluated since the terms have sums 3, 8, and 8. As before, the program exits with an error.

\$\endgroup\$
  • 11
    \$\begingroup\$ About time I posted a submission to this challenge... \$\endgroup\$ – Dennis Oct 8 '16 at 16:59
7
\$\begingroup\$

Brachylog, 13 bytes

~c@e:{<+}a!#=

Try it online!

Explanation

~c               Find a list of integers which when concatenated result in the Input
  @e             Split the integers into lists of digits
    :{<+}a       Each list of digit is stricly increasing, and compute its sum
          !      Discard all other choice points (prevents backtracking for smaller sublists)
           #=    All sums must be equal

~c will unify with the biggest sublists first.

\$\endgroup\$
6
\$\begingroup\$

Pyke, 18 bytes

mb$1m>0R+fMbms}lt!

Try it here!

mb                 -         map(int, input)
  $                -        delta(^)
   1m>             -       map(^, 1>i)
      0R+          -      [0]+^
         f         -     input.split_at(^) 
          Mb       -    deep_map(int, ^)
            ms     -   map(sum, ^)
              }    -  uniquify(^)
               lt! - len(^) == 1
\$\endgroup\$
6
\$\begingroup\$

PowerShell v2+, 100 64 61 bytes

-join([char[]]$args[0]|%{("+$_","-eq$_")[$_-le$i];$i=$_})|iex

A literal one-liner, as this is all one pipeline. Takes input as a string $args[0]. Loops through it as a char-array, each iteration placing either the current element with a + or -eq in front of it onto the pipeline based on whether the current value is -less-than-or-equal to the previous value $i. Those strings are -joined together and piped to iex (short for Invoke-Expression and similar to eval. For example, for input 2846145 this will be evaluated as +2+8-eq4+6-eq1+4+5, which is True.

That Boolean is left on the pipeline, and True/False is implicitly written at program completion.

NB - for single-digit input, the resulting digit is left on the pipeline, which is a truthy value in PowerShell.

Examples

PS C:\Tools\Scripts\golfing> 2846145,681,777,12366,2|%{"$_ -> "+(.\dennis-number-20.ps1 "$_")}
2846145 -> True
681 -> False
777 -> True
12366 -> False
2 -> 2
\$\endgroup\$
6
\$\begingroup\$

GNU sed 217 or 115

Both include +1 for -r

217:

s/./&,/g;s/^/,/g;:;s,0,,;s,2,11,;s,3,21,;s,4,31,;s,5,41,;s,6,51,
s,7,61,;s,8,71,;s,9,81,;t;s/(,1*)(1*)\1,/\1\2X\1,/;t;s/,//g
s,1X1(1*),X\1a,;t;/^1.*X/c0
/Xa*$/s,a*$,,;y,a,1,;/1X1/b;/1X|X1/c0
c1

Takes input in normal decimal

Try it online!


115:

s/^|$/,/g;:;s/(,1*)(1*)\1,/\1\2X\1,/;t;s/,//g
s,1X1(1*),X\1a,;t;/^1.*X/c0
/Xa*$/s,a*$,,;y,a,1,;/1X1/b;/1X|X1/c0
c1

Takes input as a comma separated list of the numbers digits in unary. e.g. 123 would be 1,11,111

Try it online!

\$\endgroup\$
5
\$\begingroup\$

Perl, 38 + 3 (-p) = 41 bytes

-9 bytes thanks to @Ton Hospel !

s%.%2x$&.(~$&le~$')%eg;$_=/^(2+1)\1*$/

Since there is a $', the code needs to be in a file to run. So -p counts for 3 bytes. Outputs 1 if the number is a Dennis 2.0 number, or an empty string otherwise :

$ cat dennis_numbers.pl
s%.%2x$&.(~$&le~$')%eg;$_=/^(2+1)\1*$/
$ perl -p dennis_numbers.pl <<< "1
10
12315
12314"
\$\endgroup\$
  • 1
    \$\begingroup\$ I think this is probably the best approach in perl, but you can golf it down to 42: s%.%2x$&.($&.O ge$')%eg;$_=/^(2+1)\1*$/ with the -p option (+3 because the code has $') \$\endgroup\$ – Ton Hospel Sep 30 '16 at 21:27
  • \$\begingroup\$ Indeed, using the result of the comparison instead of that random A is much better! Thanks! I don't understand the .O though... Without it, it fails on some cases, but I can't see why. \$\endgroup\$ – Dada Sep 30 '16 at 22:12
  • \$\begingroup\$ $' is the next digit and all the ones after it. So in e.g. 778 it compares 7 to 78 which to lt looks like a rising sequence. The O breaks that and compares 7O to 78 (anything above 9 in ASCII works) \$\endgroup\$ – Ton Hospel Sep 30 '16 at 22:16
  • \$\begingroup\$ Oh right, that's nice! I looked for a way to use $' or $ ` instead of my capture groups, but couldn't find it, because of that "and all the ones after it". Thanks for the tip! \$\endgroup\$ – Dada Sep 30 '16 at 22:19
  • \$\begingroup\$ Mmm, ~$&le~$' should be 1 shorter \$\endgroup\$ – Ton Hospel Sep 30 '16 at 22:24
5
\$\begingroup\$

JavaScript (ES6), 66 65 63 bytes

Saved 2 bytes thanks to @edc65

x=>[...x,p=t=z=0].every(c=>p>=(t+=+p,p=c)?(z?z==t:z=t)+(t=0):1)

Takes input as a string. Old version (only works in Firefox 30+):

x=>[for(c of(p=t=0,x))if(p>=(t+=+p,p=c))t+(t=0)].every(q=>q==+p+t)
\$\endgroup\$
  • \$\begingroup\$ Hint: [...x,0] -> [...x,p=t=z=0] \$\endgroup\$ – edc65 Oct 3 '16 at 8:14
  • \$\begingroup\$ @edc65 Thanks, I hadn't thought of that! \$\endgroup\$ – ETHproductions Oct 3 '16 at 13:07
3
\$\begingroup\$

Mathematica, 38 bytes

Equal@@Tr/@IntegerDigits@#~Split~Less&

Anonymous function. Takes a number as input, and returns True or False as output.

\$\endgroup\$
3
\$\begingroup\$

Brachylog 2, 10 bytes, language postdates challenge

ẹ~c<₁ᵐ!+ᵐ=

Try it online!

This is basically the same algorithm as @Fatalize's answer (which I didn't see until after I'd written this), but rearranged somewhat to make it golfier under Brachylog 2's syntax.

It's a full program, returning false. if it isn't a Dennis 2.0 number, or true if it is.

Explanation

ẹ~c<₁ᵐ!+ᵐ=
ẹ           Interpret the input number as a list of digits
      !     Find the first (in default order)
 ~c           partition of the digits
   <₁ᵐ        such that each is in strictly increasing order
         =  Assert that the following are all equal:
       +ᵐ     the sums of each partition

As usual for a Brachylog full program, if all the assertions can be met simultaneously, we get a truthy return, otherwise falsey. The default order for ~c is to sort partitions with fewer, longer elements first, and in Prolog (thus Brachylog), the default order's defined by the first predicate in the program (using the second as a tiebreak, and so on; here, ~c dominates, because is deterministic and thus has nothing to order).

\$\endgroup\$
2
\$\begingroup\$

MATL, 24 23 20 18 16 bytes

Tjdl<vYsG!UlXQ&=

Returns a truthy of falsey matrix

Try it Online!

Also, congrats @Dennis!

Explanation

T       % Push a literal TRUE to the stack
        %   STACK: {1}
j       % Explicitly grab the input as a string
        %   STACK: {1, '2846145'}
d       % Compute the difference between successive ASCII codes
        %   STACK: {1, [6 -4 2 -5 3 1]}
l<      % Find where that difference is less than 1
        %   STACK: {1, [0 1 0 1 0 0]}
v       % Prepend the TRUE value we pushed previously
        %   STACK: {[1 0 1 0 1 0 0]}
Ys      % Compute the cumulative sum. This assigns a unique integer label to
        % each set of increasing numbers
        %   STACK: {[1 1 2 2 3 3 3]}
G!U     % Grab the input as numeric digits
        %   STACK: {[1 1 2 2 3 3 3], [2 8 4 6 1 4 5]}
lXQ     % Compute the sum of each group of increasing digits
        %   STACK: {[10 10 10]}
&=      % Computes element-wise equality (automatically broadcasts). A
        % truthy value in MATL is a matrix of all ones which is only the case
        % when all elements are equal:
        %   STACK: {[1 1 1
        %            1 1 1
        %            1 1 1]}
        % Implicitly display the result
\$\endgroup\$
  • \$\begingroup\$ Nice use of &=! \$\endgroup\$ – Luis Mendo Sep 30 '16 at 19:24
2
\$\begingroup\$

PHP, 108 105 92 bytes

$p=-1;foreach(str_split("$argv[1].")as$d)$p>=$d?$r&&$s-$r?die(1):($r=$s)&$s=$p=$d:$s+=$p=$d;

takes input from argument, exits with 0 for Dennis-2.0 number, with 1 else.

breakdown

$p=-1;                              // init $p(revious digit) to -1
foreach(str_split("$argv[1].")as$d) // loop $d(igit) through input characters
                                    // (plus a dot, to catch the final sum)
    $p>=$d                              // if not ascending:
        ?$r                             // do we have a sum remembered 
        &&$s-$r                         // and does it differ from the current sum?
                ?die(1)                     // then exit with failure
                :($r=$s)&$s=$p=$d           // remember sum, set sum to digit, remember digit
        :$s+=$p=$d                      // ascending: increase sum, remember digit
    ;
// 
\$\endgroup\$
2
\$\begingroup\$

05AB1E, 18 bytes

SD¥X‹X¸«DgL*ꥣOÙg

Explanation

N = 12012 used as example.

                    # implicit input N = 12012
S                   # split input number to list of digits  
                    # STACK: [1,2,0,1,2]
 D                  # duplicate
                    # STACK: [1,2,0,1,2], [1,2,0,1,2]
  ¥                 # reduce by subtraction
                    # STACK: [1,2,0,1,2], [1,-2,1,1]
   X‹               # is less than 1
                    # STACK: [1,2,0,1,2], [0,1,0,0]
     X¸«            # append 1
                    # STACK: [1,2,0,1,2], [0,1,0,0,1]
        DgL*        # multiply by index (1-indexed)
                    # STACK: [1,2,0,1,2], [0,2,0,0,5]
            ê       # sorted unique
                    # STACK: [1,2,0,1,2], [0,2,5]
             ¥      # reduce by subtraction
                    # STACK: [1,2,0,1,2], [2,3]
              £     # split into chunks
                    # STACK: [[1,2],[0,1,2]]
               O    # sum each
                    # STACK: [3,3]
                Ù   # unique
                    # STACK: [3]
                 g  # length, 1 is true in 05AB1E
                    # STACK: 1

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Ruby 2.3, 56 bytes

p !gets.chars.chunk_while(&:<).map{|a|eval a*?+}.uniq[1]

Almost certainly not the golfiest way to do this, but it shows off some nice language features.

(Not newline-tolerant, so run like ruby dennis2.rb <<< '12012')

\$\endgroup\$
1
\$\begingroup\$

PHP, 144 bytes

<?php preg_match_all("/0?1?2?3?4?5?6?7?8?9?/",$argv[1],$n);foreach($n[0]as$i)if(strlen($i)&&($a=array_sum(str_split($i)))!=$s=$s??$a)die;echo 1;

I'm sure there's a much cleverer (and shorter) way to do this but it will do for now.

\$\endgroup\$
1
\$\begingroup\$

Python 2, 69 bytes

Takes input as a string.

lambda I:len(set(eval(reduce(lambda x,y:x+',+'[y>x[-1]]+y,I+' '))))<2

Explanation:

ex 1201212012

Converts to list of sums:

1+2,0+1+2,1+2,0+1+2,

Evals and converts to set.

set([3])

If the length of the set is 1, all sums are the same.

\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 58

s=>![...s,z=x=p=0].some(c=>[c>p?0:z-=(x=x||z),z-=p=c][0])

Applying my rarely useful tip https://codegolf.stackexchange.com/a/49967/21348

It scans the string char by char identifying run of ascending chars, at the end of each rum it checks if the sum is always the same

  • c : current char
  • p : previous char
  • z : running sum, at the end of a run will be compared to ...
  • x : sum to compare against, at first run is simply made equal to z

Test

f=
s=>![...s,z=x=p=0].some(c=>[c>p?0:z-=(x=x||z),z-=p=c][0])

function run()
{
  var i=I.value
  O.textContent = i + ' -> ' + f(i)
}

run()

test=`1 2 3 4 5 6 7 8 9 11 12 13 14 15 16 17 18 19 22 23 24 25 26 27 28 29 33 34 35 36 37 38 39 44 45 46 47 48 49 55 56 57 58 59 66 67 68 69 77 78 79 88 89 99 101 111 123 124 125 126 127 128 129 134 135 136 137 138 139 145 146 147 148 149 156 157 158 159 167 168 169 178 179 189 202 222 234 235 236 237 238 239 245 246 247 248 249 256 257 258 259 267 268 269 278 279 289 303 312 333 345 346 347 348 349 356 357 358 359 367 368 369 378 379 389 404 413 444 456 457 458 459 467 468 469 478 479 489 505 514 523 555 567 568 569 578 579 589 606 615 624 666 678 679 689 707 716 725 734 777 789 808 817 826 835 888 909 918 927 936 945 999`.split` `

numerr=0
for(i=1; i<1000; i++)
{
  v = i + '';
  r = f(v);
  ok = r == (test.indexOf(v) >= 0)
  if (!ok) console.log('Error',++numerr, v)
}  
if(!numerr) console.log('All test 1..999 ok')
<input id=I value=612324 type=number oninput='run()'>
<pre id=O>

\$\endgroup\$
1
\$\begingroup\$

Pyth, 20 bytes

Two versions

!t{sMcJjQThMx1<R0.+J
LS{b!t{sMhyI#I#./jQT

Try the first one online!

Try the second one online!

\$\endgroup\$
0
\$\begingroup\$

Ruby, 117 105 85 bytes

# original (117):
j,k=0,?0;"#{i}".chars.group_by{|n|n>k||j=j+1;k=n;j}.values.map{|a|a.map(&:to_i).reduce(&:+)}.reduce{|m,n|n==m ?m:nil}

# inspired by PHP regexp approach (105):
"#{i}".scan(/0?1?2?3?4?5?6?7?8?9?/).map{|a|a.chars.map(&:to_i).reduce(&:+)}.reduce{|m,n|!n||n==m ?m:nil}

# some number comparison simplification (85):
!"#{i}".scan(/0?1?2?3?4?5?6?7?8?9?/).map{|a|a.chars.map(&:to_i).reduce(&:+)}.uniq[1]

This would return the integer of this dennis number or nil if not a dennis number. All integers will be considered true in ruby as well nil is considered false. i is the integer that is being check.

Third version actually returns true and false.

P.S. tested to return 172 integers from 1 to 1000 as in the answer.

\$\endgroup\$
0
\$\begingroup\$

APL, 23 bytes

{1=≢∪+/↑N⊂⍨1,2>/N←⍎¨⍕⍵}

Explanation:

  • N←⍎¨⍕⍵: get the individual digits in the input, store in N
  • N⊂⍨1,2>/N: find the sublists of strictly increasing numbers in N
  • +/↑: sum each sublist
  • 1=≢∪: see if the resulting list has only one unique element
\$\endgroup\$
0
\$\begingroup\$

Add++, 109 bytes

D,g,@@#,BF1_B
D,k,@@#,bR$d@$!Q@BFB
D,f,@,BDdVÑ_€?1€_0b]$+€?dbLRBcB*BZB]GbL1+b]+qG€gd€bLÑ_0b]$+BcB]£k€¦+Ñ=1$ª=

Try it online!

How it works

We define our 3 functions, \$f\$, \$g\$ and \$k\$. \$f\$ is the main function, which transforms the input to the correct output.

\$f(x)\$

First, we convert the input \$x\$ into a list of digits, then take the forward increments. Next, we take the sign of each increment. For increasing subsequences, this yields a subsequence of \$1\$, for equal subsequences, such as \$[4, 4, 4]\$, this yields \$0\$s and for decreasing sections, \$-1\$ is returned. We then take the complement of each of these signs, to turn \$1\$ into a falsey value, and everything else into a truthy value. Next, \$0\$ is prepended to this array, and we take the sign of each element again. This yields an array, \$A\$, of \$0\$ and \$1\$, with the first element always being \$0\$.

We then yield the range \$[1, 2, ... length(A)]\$ and remove the elements that correspond to \$0\$ in \$A\$. This leaves us with a second array, \$A'\$. We then push the number of digits in the input, add one and append this number to \$A'\$. We then deduplicate \$A'\$, to yield a new array, \$A''\$.

Next, we use the \$g\$ helper function. As \$g\$ is dyadic (takes 2 arguments), it behaves slightly differently when paired with the each operator, . Dyadic functions pop a value from the stack and bind that value as their right argument to create a partial monadic function. This partial function is then mapped over each element in the argument. Here, the bound right argument is the digits of the input and the partial function is mapped over \$A''\$.

\$g(x, y)\$

Let's take a look at just one iteration of \$g(x, y)\$ where \$x := [1, 2, 0, 1, 2]\$ and \$y = 3\$. Note that \$3\$ is the first index in \$A''\$ where the signs from \$A\$ corresponded with \$1\$, rather than \$0\$. In fact, for \$x = 12012\$, we can see that \$A'' = [3, 6]\$. \$3\$ is the only non-zero index in \$A\$, and \$6\$ is the length of \$x\$ plus one.

So, for \$g([1, 2, 0, 1, 2], 3)\$ the following happens: First, we swap the two arguments so that the stack has the digits below the index. We then flatten the array and decrement the index. So far, the stack looks like [1 2 0 1 2 2]. We then perform the head command. We pop the index from the top f the stack and take that many characters from the stack, starting at the bottom. This yields \$[1, 2]\$, which is then returned by \$g\$.

So, \$g(x, y)\$ is mapped over each element \$y \in A''\$, which returns a series of prefixes of the input of various increasing lengths. This part could get slightly confusing, so we'll work through it with the example input of \$x := 12012\$. After the mapping of \$g\$, the stack currently looks like

[[[1 2] [1 2 0 1 2]]]

We then push an array containing the length of each array in the top element, or in this instance, the array \$[2, 5]\$. This is the same as \$A'' - 1\$, if the \$-\$ operator maps, but it takes more bytes to use this relationship. Next, the forward differences of the lengths is taken, and \$0\$ is prepended, yielding, in this example, \$[0, 3]\$. This new array is then zipped with the results from \$g\$ to create \$B\$ and the starmap operator is run over each pair.

\$k(x, n)\$

The starmap operator uses the function \$k\$ as its argument, and works by taking a dyadic function and a nested array. The array must consist of pairs, such as \$[[1, 2], [3, 4], [5, 6]]\$, and the dyadic function is mapped over each pair, with each element of the pairs being the left and right arguments respectively.

Here, our example nested array is \$[[[1, 2], 0], [[1, 2, 0, 1, 2], 3]]\$ and our function is \$k\$. We'll focus simply on \$k([1, 2, 0, 1, 2], 3)\$ for now.

\$k(x, n)\$ starts, similar to \$g\$, by swapping the two arguments, so that the array is the top of the stack. We then reverse the array and swap the arguments back. Now, \$n = 0\$, we want to leave the array unchanged, so we duplicate the integer and rotate the top three arguments, so that the stack has the format of \$[n, x, n]\$. Next, we return the array if \$n = 0\$. Otherwise, the top element is discarded, and we arrange the stack back to how it was i.e. with the reversed array at the bottom and the integer at the top, or in our example: \$[[2, 1, 0, 1, 2], 3]\$. We then flatten the stack, and take the first \$n\$ elements of \$x\$. These elements are then returned and replace \$x\$ in \$B\$.

For our input, this returns \$[0, 1, 2]\$. (Strictly speaking, it returns\$[2, 1, 0]\$, but order doesn't matter for the rest of the program).

After \$k(x, n)\$ is mapped over each pair \$(x, n) \in B\$, we take the sum of each pair, then check that each element is equal, by asserting that each neighbouring pair are equal, and then asserting that each of those equality tests result in \$1\$ (a truthy value). Finally, this result is returned.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.