18
\$\begingroup\$

The rundown

Create a program that generates an array of random length with random numbers, then apply a series of rules that alter the array. After the rules have been applied, print the sum of the array unless specified otherwise

Array setup

The array must be a random length between 5 and 10 inclusive, with random integers between 1 and 20 inclusive. Each array length should have equal probability of happening and each integer should have an equal probability of being picked per element.

The 7 rules

The rules should act as if they were applied in sequence (eg: rule 1 acts before rule 2) and are only applied once. For proof of rule application, the array must be printed to console after each rule application and once before any rules are applied.

  1. If the array contains a 7, subtract 1 from every element
  2. If rule 1 is applied and the array now contains a 0, add 1 to each element
  3. If the array contains a 13, exclude the 13, and all elements that follow, from the array
  4. If the array contains a 2, exclude all odd numbers
  5. If the array contains a 20, and the third element is even, return 20 as the sum then terminate. If a 20 is present and the third element is odd, return 20 times the length of the array as the sum then terminate.
  6. If the sum is greater than 50, remove the last element repeatedly until it is less than or equal to 50
  7. If the array contains a 16, print the sum in both decimal and hexadecimal.

Example

Here is an initial array,

[20, 2, 5, 7, 14, 8]

Rule 1 can be applied:

[19, 1, 4, 6, 13, 7]

Rule 3 is applied next:

[19, 1, 4, 6]

No other rules are needed, so the program returns 30 as the sum.

Notes

  • I'm not an experienced code golfer, although I can say my personal record is in Python 3 with 369 bytes.
  • The rules don't have to actually be applied in order, but have to act as if they did.
\$\endgroup\$
17
  • 1
    \$\begingroup\$ How random does "random" have to be? \$\endgroup\$
    – hyper-neutrino
    Commented Apr 13, 2017 at 4:21
  • 1
    \$\begingroup\$ @HyperNeutrino it can be as sudo-random as you want, but not challenge throwing. Repeats are allowed. \$\endgroup\$
    – Graviton
    Commented Apr 13, 2017 at 4:26
  • \$\begingroup\$ How are you going to check if we actually applied the rules? I can just generate a random number under 50 and it would still technically not break any of the rules, and I could just say it "followed" the rules. EDIT: I realise now that this won't work, but people are going to find ways to circumvent the random rules. Are you going to prevent that? \$\endgroup\$
    – clismique
    Commented Apr 13, 2017 at 4:29
  • 1
    \$\begingroup\$ At the moment, choosing one of the two arrays [3 3 3 3 4 3] and [4 4 3 4 4], each with probability 50%, is in compliance with what's written under "array setup". So I can just output 19 every time? (Of course, what I really think is that the definition of "random" needs to be clarified.) \$\endgroup\$ Commented Apr 13, 2017 at 6:11
  • 3
    \$\begingroup\$ If the array contains a 20, and the third element is even/odd, what if the array has less than 3 elements at this step? \$\endgroup\$
    – Emigna
    Commented Apr 13, 2017 at 9:54

19 Answers 19

8
\$\begingroup\$

Python 3, 294 301 287 356 bytes

import random as r
r=r.randint
k=[r(i)+1for i in[20]*r(5,11)]
p=print
if 7in k:k=[i-1for i in k]
p(k)
if 0in k:k=[i+1for i in k]
p(k)
i=k.find(13)
if not~i:k=k[:i]
p(k)
if 2in k:k=[i for i in k if~i%2]
p(k)
a=0
z=len(k)>2and k[2]%2
if 20in k:a=20*len(k)**z
if~z:p(k)
while sum(k)>50:k=k[:-1]
if~z:p(k)
if a:p(a)
else:a=sum(k);p(a,hex(a)*(16in k))
if~z:p(k)

I don't know how you're going to prevent people circumventing the rules, but this one uses the procedure specified.

+7 bytes; thanks to @YamB for saving a few bytes; added a lot more to fix a previous error.
-14 bytes thanks to @RootTwo and myself and also corrected the error.
+83 bytes; this is getting horribly long because OP keeps changing the rules. -some number of bytes thanks to @ZacharyT

\$\endgroup\$
10
  • \$\begingroup\$ All checks out to me, thanks for being honest. \$\endgroup\$
    – Graviton
    Commented Apr 13, 2017 at 4:40
  • \$\begingroup\$ You can save 4 bytes by importing 'randint as r' and changing 'if 7in k and 1not in k:k=[i-1...' to 'if 7in k:k=[i+1-int(1in k)...' \$\endgroup\$
    – Graviton
    Commented Apr 13, 2017 at 4:44
  • \$\begingroup\$ When initializing k, you don't need the value of i, so you can save 6 bytes with k=[r(1,20)for _ in'-'*r(5,11)]. You can save another byte using k=[i+~-(1in k)*(7in k)for i in k] for rules 1 and 2. \$\endgroup\$
    – RootTwo
    Commented Apr 15, 2017 at 6:49
  • 1
    \$\begingroup\$ @Notts90 The rules were changed after I wrote this challenge. I will fix it when I get to a computer. Thanks. \$\endgroup\$
    – hyper-neutrino
    Commented Apr 18, 2017 at 10:17
  • \$\begingroup\$ On lines five and seven, you have an unneeded space after the 1, and you can change the print on the second and third to last lines to p. And you ... haven't updated your bytecount. \$\endgroup\$
    – Adalynn
    Commented Jun 14, 2017 at 14:49
6
\$\begingroup\$

05AB1E, 91 bytes

5TŸ.RF20©L.R})=D7åi<=D0åi>=}}D13åiD13k£=}D2åiDÈÏ=}D®åiDgs2èÉ®si*},q}[DO50›_#¨=]D16åiDOH,}O,

Try it online! or With input

\$\endgroup\$
2
  • \$\begingroup\$ 84 bytes, and potentially correct? Different? No idea. tio.run/nexus/… \$\endgroup\$ Commented Apr 14, 2017 at 18:25
  • \$\begingroup\$ @carusocomputing: I haven't looked through it thoroughly, but it doesn't generate the random array in the beginning nor does it print intermediate results. Will be a bit longer when adding those parts. \$\endgroup\$
    – Emigna
    Commented Apr 16, 2017 at 8:14
6
\$\begingroup\$

JavaScript, 344 342 340 342 335 331 333 313 311 305 298 297 290 289 283 279 271 265 263 bytes

Following this exchange* in the challenge's comments and after much deliberation I opted to use new Date as the seed for the random number generator instead of Math.random(). Doing so means that all the integers in the array will be of the same value.

Now a full programme, rather than a function

D=new Date
P=print
I=n=>~a.indexOf(n)
C=(n,c)=>I(n)&&P(a=+c?a.map(x=>x+c):a.filter(c))
P(a=[...Array(D%6+5)].map(x=>D%20+1))
C(7,-1)
C(s=0,1)
C(13,(_,x)=>x<~I(13))
C(2,x=>x%2)
P(I(t=20)?a[2]%2?t*a.length:t:P(a.filter(x=>s+x<51?s+=x:0))|I(16)?[s,s.toString(16)]:s)

Try it online! or with Math.random


*Screenshot, in case it's deleted:

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

C (gcc), 621 619 593 585 570 562 557 552 529 517 500 482 461 444 442 441 438 bytes

There's a whole lot of golfing needed here... Fixed a bug where it would print the hexidecimal once for each 16 in the list...

Special thanks to ZacharyT with the golf help

#define R r[i]
#define P printf("%d "
#define L for(d=i=0;i<l;i++)
d,i,j,l,r[11];p(i){L P,R);puts("");}main(){srand(time(0));for(l=5+rand()%5;i<l;R=1+rand()%20,i++);for(p();i--;)if(R==7){L--R;j=i=1;}for(p();j&&i<l;i++)if(!R){L++R;j=i=l;}p();L if(R==13)l=i;p();L if(R==2)for(d=1;d;)L if(R&1)for(d=1,--l;i<=l;i++)R=r[i+1];p();L if(R==20)return P,r[3]&1?20*l:20);for(j=i=0;i<l&&j+R<51;j+=R,i++);l=i;p();P,j);L if(R==16)printf("0x%x",j,i=l);}

Try it online!

\$\endgroup\$
11
  • 1
    \$\begingroup\$ Even though you can still golf a lot, you're already 1 byte below my Java answer.. XD Let's see if I can golf it somehow to beat your current submission. ;) \$\endgroup\$ Commented Apr 13, 2017 at 14:34
  • \$\begingroup\$ Ok, found something for -3 bytes ;p \$\endgroup\$ Commented Apr 13, 2017 at 14:42
  • \$\begingroup\$ If you can golf this down, you might be able to get a "crossed out 444 is still 444" in there! :D \$\endgroup\$
    – hyper-neutrino
    Commented May 13, 2017 at 2:44
  • \$\begingroup\$ @HyperNeutrino Golfed off another 2 bytes \$\endgroup\$
    – cleblanc
    Commented May 15, 2017 at 12:50
  • \$\begingroup\$ Yay! Nice job :D \$\endgroup\$
    – hyper-neutrino
    Commented May 15, 2017 at 12:51
4
\$\begingroup\$

K (ngn/k), 160 147 139 bytes

-13 from consolidating 0N! prints/other tweaks

-8 by converting to ngn/k

{0N!'|(a@:&(~2!a)|^a?2;a:(a?13)#a;a+:|/~a;a-:|/a=7;a:1+(*5+1?6)?20);$[^a?20;;:20*(1;#a)2!a 2];0N!a@:&51>+\a;(+/a),$[^a?16;!0;,`hex@`c$+/a]}

Try it online!

From the beginning to the end...

  • 0N!'| print each of the following in reverse order (when building lists, ngn/k executes the right-most/last list item first, the second-to-last item second, etc. For ease of explanation, the below are listed in the order they are executed)
    • a:1+(*5+1?6)?20 generate 5-10 random numbers between 1 and 20, storing in a
    • a-:|/a=7; decrement a if it contains a 7
    • a+:|/~a; increment a if it contains a 0
    • a:(a?13)#a; take elements occurring before the first 13
    • a@:&(~2!a)|^a?2; if a 2 is present, remove odds from a
  • $[^a?20;;:20*(1;#a)2!a 2]; if 20 is present, check the third value a 2 and early return from the function (otherwise do nothing)
  • 0N!a@:&51>+\a; remove values where the cumulative sum up to that point is >50
  • $[^a?16;+/a;(+/a;`hex@`c$+/a)] return either the sum of a (if no 16 is present), or return the sum as both an integer and in hexadecimal representation (the latter as a string)
\$\endgroup\$
3
\$\begingroup\$

JavaScript (ES6), 296 295 290 289 bytes

A full program that logs the initial array, the intermediate results and the final sum to the console.

f="z=[...Array(5+6j)]Z1+20jw7`-1w0`+1w13_qi+1<-kw2_qn&1^1w20_z[2]&1?a.length*20:20);else{q(s+=n)<51,s=0w16_b.toString(16_;b)}zconsole.log(aw_;if(k=~a.indexOf(v((n,i)=>qz=a.filtervj*Math.random()|0bz.reducevn+i,0)`_z=aZn_))Z.mapv";for(g of "Z_`bjqvwz")e=f.split(g),f=e.join(e.pop());eval(f)

How it works

This was compressed using this JS packer.

Breakdown:

  • Packed string: 226 225 bytes
  • Unpacking code: 69 64 bytes

Below is the original source code with some additional whitespace and line feeds for readability. Rather than applying standard golfing tricks, it was written in a way that produces as many repeating strings as possible in order to please the packer. For instance, the syntax if(k=~a.indexOf(N)) is duplicated everywhere although k is only used in the 3rd rule.

console.log(a=[...Array(5+6*Math.random()|0)].map((n,i)=>1+20*Math.random()|0));
if(k=~a.indexOf(7))
  console.log(a=a.map((n,i)=>n-1));
if(k=~a.indexOf(0))
  console.log(a=a.map((n,i)=>n+1));
if(k=~a.indexOf(13))
  console.log(a=a.filter((n,i)=>i+1<-k));
if(k=~a.indexOf(2))
  console.log(a=a.filter((n,i)=>n&1^1));
if(k=~a.indexOf(20))
  console.log(a[2]&1?20*a.length:20);
else {
  console.log(a=a.filter((n,i)=>(s+=n)<51,s=0));
  if(k=~a.indexOf(16))
    console.log(a.reduce((n,i)=>n+i,0).toString(16));
  console.log(a.reduce((n,i)=>n+i,0))
}

Unpacking methods

The original unpacking code is:

f="packed_string";for(i in g="ABCDEFGHI")e=f.split(g[i]),f=e.join(e.pop());eval(f)

All the following ES6 variants have exactly the same size:

eval([..."ABCDEFGHI"].reduce((f,g)=>(e=f.split(g)).join(e.pop()),"packed_string"))
[..."ABCDEFGHI"].map(g=>f=(e=f.split(g)).join(e.pop()),f="packed_string")&&eval(f)
eval([..."ABCDEFGHI"].map(g=>f=(e=f.split(g)).join(e.pop()),f="packed_string")[8])

The only way I've found so far to shave off a few bytes is to use for ... of:

f="packed_string";for(g of "ABCDEFGHI")e=f.split(g),f=e.join(e.pop());eval(f)
\$\endgroup\$
9
  • \$\begingroup\$ Reading this on a phone so I may be wrong but, in your unpacked code, it looks like rule 2 is being applied regardless of whether or not rule 1 is. \$\endgroup\$
    – Shaggy
    Commented Apr 13, 2017 at 20:08
  • 1
    \$\begingroup\$ @Shaggy That's correct. But you can't get a zero unless rule 1 is triggered. \$\endgroup\$
    – Arnauld
    Commented Apr 13, 2017 at 21:34
  • \$\begingroup\$ D'oh! Of course! Man, I've been having a ridiculous number of brainfarts during this challenge :( \$\endgroup\$
    – Shaggy
    Commented Apr 13, 2017 at 21:48
  • 1
    \$\begingroup\$ @Shaggy Unfortunately not. However, we can save one byte with n&1^1 (it doesn't get packed at all, but is just one byte shorter than !(n&1)). I thought about that at some point and forgot to include it. \$\endgroup\$
    – Arnauld
    Commented Apr 14, 2017 at 13:09
  • 1
    \$\begingroup\$ @Shaggy Ahah! Nice job! \$\endgroup\$
    – Arnauld
    Commented May 5, 2017 at 17:30
2
\$\begingroup\$

First try at code golf!

Already beat by other javascripters! Dangit! I will improve!!! =)

Javascript -> 550 402 bytes

Could definitely be improved. Compressed Now:

f="ba=[];bl;yz5+5`^=0;i<y;i++)a[i]z20+1|~7j-1|~0j+1|}}~13_l=indexOf(13`ql,y-l-Y_^ in a)if(a[i]%2)qi,Y0)&&(!a[3]%2_k'20'`throw new Error(`}do{l=Vreduce((X,num)=>X+num`ifW)qy-1,1`}whileW|kl`~16))kl.toString(16)`~if(Vincludes(|`ka`z=Zound(Zandom()*yVlengthqVsplice(kalert(j_Vmap((i)=>ibvar `);_)){^for(biZMath.rY1|}~2XtotalW(l>50Va.";for(i in g="VWXYZ^_`bjkqyz|~")e=f.split(g[i]),f=e.join(e.pop());eval(f)

Originial:

var a=[];var l;a.length=Math.round(Math.random()*5+5);for(var i=0;i<a.length;i++)a[i]=Math.round(Math.random()*20+1);alert(a);if(a.includes(7)){a.map((i)=>i-1);alert(a);if(a.includes(0)){a.map((i)=>i+1);alert(a);}}if(a.includes(13)){l=indexOf(13);a.splice(l,a.length-l-1);alert(a);}if(a.includes(2)){for(var i in a)if(a[i]%2)a.splice(i,1);alert(a);}if(a.includes(20)&&(!a[3]%2)){alert('20');throw new Error();}do{l=a.reduce((total,num)=>total+num);if(l>50)a.splice(a.length-1,1);}while(l>50);alert(a);alert(l);if(a.includes(16))alert(l.toString(16));
\$\endgroup\$
2
\$\begingroup\$

PowerShell, 525 413 bytes

filter a{"$a"};0..(4..9|random)|%{$a+=@(1..20|random)};a;if(7-in$a){$a=($a|%{$_-1});a;if(0-in$a){$a=($a|%{$_+1});a}}$b=$a;$a=@();foreach($z in $b){if($z-ne13){$a+=@($z)}else{a;break}}if(2-in$a){$a=($a|?{$_%2-eq0});a}if(20-in$a){if($a[2]%2){20*$a.count;exit}else{20;exit}}while(($h=$a-join'+'|iex)-gt50){$a=$a[0..($a.count-2)];a}if(16-in$a){$l=0..9+'a b c d e f'-split' ';$q=[math]::floor($h/16);"$q"+$l[$h%16]};$h

Try it online!

I wanted to attempt this one although I figured I wouldn't beat the answers already here :P I have been attempting to golf this down still, I'm sure it's possible with less bytes. Found a better method for hex, but could probably still improve.

Had to cast $a to a string so many times it was better to create a filter for it...

There were quite a few easy golfs I missed such as parentheses and spaces. Might still be some out there?

Somewhat easier to read code:

filter a{"$a"};0..(4..9|random)|%{$a+=@(1..20|random)};a;
if(7-in$a){$a=($a|%{$_-1});a;if(0-in$a){$a=($a|%{$_+1});a}}
$b=$a;$a=@();foreach($z in $b){if($z-ne13){$a+=@($z)}else{a;break}}
if(2-in$a){$a=($a|?{$_%2-eq0});a}
if(20-in$a){if($a[2]%2){20*$a.count;exit}else{20;exit}}
while(($h=$a-join'+'|iex)-gt50){$a=$a[0..($a.count-2)];a}
if(16-in$a){$l=0..9+'a b c d e f'-split' ';$q=[math]::floor($h/16);"$q"+$l[$h%16]};$h
\$\endgroup\$
2
\$\begingroup\$

Ruby 2.4, 260 bytes

Ruby 2.4 is required for Enumerable#sum.

p a=(1..s=5+rand(5)).map{1+rand(19)}
a.map!{|i|i-1}if a.index 7
p a
a.map!{|i|i+1}if a.index 0
p a
a.pop s-(a.index(13)||s)
p a
a.reject! &:odd?if a.index 2
p a
a.index(20)?p(20*[1,s][(a[2]||1)%2]):((a.pop;p a)while a.sum>50
p m=a.sum;puts"%x"%m if a.index 16)

Try it online! (Neither repl.it nor tio.run support Ruby 2.4 yet, so this online version replaces sum with inject(:+), which has the same behavior.)

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

Java 10, 622 619 618 613 576 575 bytes

v->{var L=new java.util.Stack<Integer>();String r="",N="\n";int c=(int)(Math.random()*6+5),i=c;for(;i-->0;L.add((int)(Math.random()*20+1)));r+=L+N;if(L.contains(7)){for(;++i<c;L.set(i,L.get(i)-1));r+=L+N;}if(L.contains(i=0)){for(;i<c;L.set(i,L.get(i++)+1));r+=L+N;}if((i=L.indexOf(13))>=0){L.subList(i,c).clear();r+=L+N;}if(L.contains(2)){for(i=0;i<L.size();)if(L.get(i)%2>0)L.remove(i);else++i;r+=L+N;}if(L.contains(20))return r+20*(L.get(2)%2<1?1:L.size());i=0;for(var x:L)i+=x;for(;i>50;)i-=L.remove(L.size()-1);return r+L+N+(L.contains(16)?Byte.valueOf(i+"",16)+N:"")+i;}

-1 byte thanks to @Poke
-6 bytes thanks to @ceilingcat.

Try it online.

Explanation:

v->{                          // Method with empty unused parameter and String return
  var L=new java.util.Stack<Integer>();
                              //  Integer-list, starting empty
  String r="",                //  Result-String, starting empty
         N="\n";              //  Temp-String `N`, containing a newline
  int c=(int)(Math.random()*6 //  Get a random integer in the range [0,6]
              +5),            //  And add 5
  i=c;for(;i-->0;             //  Loop that amount of times:
    L.add((int)(Math.random()*20+1)));
                              //   Add a random integer in the range [1,20] to the list
  r+=L+N;                     //  Append the current list + newline to the result-String
  if(L.contains(7)){          //  If the list now contains a 7:
    for(;++i<c;L.set(i,L.get(i)-1));
                              //   Decrease each value by 1
    r+=L+N;}                  //   And append the current list + newline again
  if(L.contains(i=0)){        //  If the list now contains 0:
    for(;i<c;L.set(i,L.get(i++)+1));
                              //   Increase each value by 1
    r+=L+N;}                  //   And append the current list + newline again
  if((i=L.indexOf(13))>=0){   //  If the list now contains a 13:
    L.subList(i,c).clear();   //   Remove all values from that 13 onward from the list
    r+=L+N;}                  //   Append the current list + newline again
  if(L.contains(2)){          //  If the list now contains a 2:
    for(i=0;i<L.size();)      //   Loop over the list:
      if(L.get(i)%2>0)        //    If the current value is odd:
        L.remove(i);          //     Remove it 
      else                    //    Else:
        ++i;                  //     Skip it, and go to the next value
    r+=L+N;}                  //   Append the current list + newline again
  if(L.contains(20))          //  If the list now contains a 20:
    return r                  //   Return the result-String
           +20*               //   And append 20 multiplied by:
               (L.get(2)%2<1? //    If the third item is even:
                 1            //     Multiply the 20 by 1 so it'll remain 20
                :             //   Else (it's odd instead):
                 L.size());   //    Multiply the 20 by the list-size
  i=0;for(var x:L)i+=x;       //   Set `i` to the sum of the list
  for(;i>50;)                 //  Loop as long as the list-sum is larger than 50:
    i-=L.remove(L.size()-1);  //   Remove the last item of the list
  return r                    //  Return the result-String
         +L+N                 //  Appended with the current list + newline again
         +(L.contains(16)?    //  If the list now contains a 16:
            Byte.valueOf(i+"",16)+N
                              //   Append the sum as hexadecimal
           :                  //  Else:
            "")               //   Append nothing
         +i;}                 //  And append the sum (as regular base-10 integer)

Sample outputs:
Comments behind the sample outputs aren't printed, but I added them as clarification.

[17, 5, 3, 1, 16, 17, 11, 7, 13]   // Initial print (size 9)
[16, 4, 2, 0, 15, 16, 10, 6, 12]   // Rule 1 (contains a 7)
[17, 5, 3, 1, 16, 17, 11, 7, 13]   // Rule 2 (contains a 0)
[17, 5, 3, 1, 16, 17, 11, 7]       // Rule 3 (contains a 13)
[17, 5, 3, 1, 16]                  // Rule 6 (sum must be <= 50)
66                                 // Rule 7 (contains a 16 -> print as Hexadecimal)
42                                 // Print sum as integer

[4, 18, 17, 12, 11, 8]             // Initial print (size 6)
[4, 18, 17]                        // Rule 6 (sum must be <= 50)
39                                 // Print sum as integer

[4, 14, 6, 14, 7, 20, 2, 2]        // Initial print (size 8)
[3, 13, 5, 13, 6, 19, 1, 1]        // Rule 1 (contains a 7)
[3]                                // Rule 3 (contains a 13)
[3]                                // Print is always done after rule 6
3                                  // Print sum as integer
\$\endgroup\$
7
  • 1
    \$\begingroup\$ I'm down to 594 bytes now :-D \$\endgroup\$
    – cleblanc
    Commented Apr 13, 2017 at 15:46
  • \$\begingroup\$ @cleblanc I see you're down to 444 now.. I can't compete with that with Java. :) (Funny to say that since 444 is no where near winning compared to all the other answers..) \$\endgroup\$ Commented Apr 14, 2017 at 13:29
  • \$\begingroup\$ I know it, even the golfing languages like 05AB1E are almost 100 bytes long. This challenge was a pain. \$\endgroup\$
    – cleblanc
    Commented Apr 14, 2017 at 13:34
  • \$\begingroup\$ Can you leave your list generic List a = new ArrayList()? Might save some bytes. You might need to add a typecast when doing actual arithmetic, though. If not, Long is shorter than Integer \$\endgroup\$
    – Poke
    Commented Apr 18, 2017 at 20:03
  • \$\begingroup\$ @Poke With a generic List I have to use an (int) cast five times, as well as change the for-each loop from int to Object and add a sixth cast. As for Long: thanks, that saves 1 byte :) (still have to change the for-each from int to long, and r.nextInt(20)+1 to r.nextInt(20)+1L). \$\endgroup\$ Commented Apr 19, 2017 at 6:45
1
\$\begingroup\$

R (3.3.1), 325 bytes

Pretty naive implementation; I think I can probably make it a bit shorter.

s=sample(1:20,sample(5:10,1));print(s);if(7%in%s){s=s-1;print(s);if(0%in%s)s=s+1;print(s)};if(13%in%s){s=s[1:(which(s==13)-1)];print(s)};if(2%in%s){s=s[!(s%%2)];print(s)};if(20%in%s){if(s[3]%%2){20*length(s);print(s)}else{20;print(s)}};while(sum(s)>50){s=s[-length(s)];print(s)};if(16%in%s){print(as.hexmode(sum(s)))};sum(s)
\$\endgroup\$
0
\$\begingroup\$

MATLAB, 275 bytes

I originally planned on maybe a one-liner Octave answer, but requiring output of all applied rules thwarted my plans. Instead, a fairly straightforward MATLAB answer with a few interesting optimisations, e.g. the use of cumsum instead of the obvious while for rule 6. Still, a lot of the byte count is wasted on ifs to prevent output if a rule is not applied.

A=randi(20,1,randi(6)+4)
if any(A==7)
A=A-1
if any(~A)
A=A+1
end;end
q=find(A==13,1);if q
A=A(1:q-1)
end
if any(A==2)
A=A(2:2:end)
end
if any(A==20)
if mod(A(3),2)
20*length(A)
else
20
end;return;end
q=cumsum(A)<51;if any(~q)
A=A(q)
end
q=sum(A)
if(any(A==16))
dec2hex(q)
end

Try it online!

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

Scala 587 bytes one liner

import scala.util.Random;object A{def main(args:Array[String])={val s=5+Random.nextInt(6);var a=new Array[Int](s);for(i<-1 to s){a(i-1)=1+Random.nextInt(20)};p(a);if(a.contains(7)&& !a.contains(1)){a.map(a=>a-1);p(a)};if(a.contains(13)){if(a(0)==13)a=new Array[Int](0)else a=a.slice(0,a.indexOf(13));p(a)};if(a.contains(2)){a=a.filter(pred=>pred%2==0);p(a)};if(a.contains(20)){if(a(2)%2==0)println(20)else println(20*a.length)}else{while(a.sum>50)a=a.dropRight(1);val u=a.sum;if(a.contains(16))println(Integer.toHexString(u));println(u)}};def p[T](a: Array[T])=println(a.mkString(","))}

Scala, 763 bytes as is

import scala.util.Random
object TA {
  def main(args:Array[String])={
    val s=5+Random.nextInt(6)
    var a=new Array[Int](s)
    for (i<-1 to s)
      a(i-1)=1+Random.nextInt(20)
    p(a)
    if(a.contains(7) && !a.contains(1)){
      a.map(a=>a-1)
      p(a)
    }
    if(a.contains(13)){
      if (a(0)==13) a=new Array[Int](0) else a=a.slice(0,a.indexOf(13))
      p(a)
    }
   if(a.contains(2)){
      a=a.filter(pred=>pred%2== 0)
      p(a)
    }
    if(a.contains(20)){
      if (a(2)%2==0) println(20) else println(20*a.length)
    }else{
      while(a.sum>50)
        a=a.dropRight(1)
      val u =a.sum
      if (a.contains(16)) println(Integer.toHexString(u))
      println(u)
    }
  }
  def p[T](a: Array[T])={
    println(a.mkString(","))
  }
}
\$\endgroup\$
4
  • \$\begingroup\$ Since this is a code-golf question we do ask that you make at least the easy golfs such as removing unnecessary whitespace. \$\endgroup\$
    – Wheat Wizard
    Commented Apr 14, 2017 at 2:29
  • \$\begingroup\$ I added the one line low byte version \$\endgroup\$ Commented Apr 17, 2017 at 16:54
  • \$\begingroup\$ I don't know Scala, but is the space in a: Array[T] required? You have no space in args:Array[String], which is what resulted in my inquiry. \$\endgroup\$
    – Adalynn
    Commented Jun 13, 2017 at 19:26
  • \$\begingroup\$ no I think I missed it. \$\endgroup\$ Commented Jun 13, 2017 at 20:55
0
\$\begingroup\$

MATLAB, 228 241bytes

a=randi(20,1,randi(6)+4)
b=@any; 
a=a-b(a==7)
a=a+b(a==0)
a(find(a==13,1):end)=[]
a(and(mod(a,2),b(a==2)))=[]
if b(a==20)
a=[a 0 0 0];
s=20*(1+mod(a(3),1)*(numel(a)-4))
else
a(cumsum(a)>50)=[]
s=sum(a)
if b(a==16)
h=['0x' dec2hex(s)]
end
end

This will apply all rules in order, printing the array value after each step.

The program will crash on rule 5 if the resulting number of elements is less than three. There is currently nothing to say what should happen if there is no third element, so I am assuming that a crash is acceptable. The program will now print 20 if there are less than 3 elements and one or more is a 20.

Interestingly step 2 can be applied regardless of whether step 1 was. This is because the input array will never have a 0 in it meaning that if there are any 0's in the array it must be as a result of step 1 having occurred.

All rules are applied in turn, up until 5, even if there are no changes made. As a result the array will be printed at the start and then after each step up until 5. After step 5 you will either get the sum if it is applied, or no output until after step 6. An extra line containing a could be added after the else statement to ensure that the array value is printed after step 5 at the cost of 2 bytes.


I'd also like to mention that I didn't look at the other answers until after I had written this. I see now that there is another MATLAB answer with some similarities - all of which are coincidental.

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

Python 3, 297 293 289, 278 bytes

As Arnauld spotted, you can't get 0 unless rule 1 was applied, which saved on indenting. Thanks to everyone else who commented with suggestions too.

from random import*
p=print
a=b=sample(range(1,20),randint(5,10))
p(a)
if 7in a:a=[i-1for i in a];p(a)
if 0in a:a=b;p(a)
if 13in a:a=a[:a.index(13)];p(a)
if 2in a:a=[i for i in a if~i%2];p(a)
if 20in a and~a[2]%2:a=[20]
while sum(a)>50:a=a[:-1]
b=sum(a)
p(b)
if 16in a:p(hex(b))

Try it online

\$\endgroup\$
2
  • \$\begingroup\$ I don't think you need the space between the and and ~. \$\endgroup\$
    – Adalynn
    Commented Jun 14, 2017 at 14:50
  • \$\begingroup\$ i believe from random import* a=b=sample(range(1,20),randint(5,10)) saves some bytes since you can delete line 2. \$\endgroup\$
    – nocturama
    Commented Jun 16, 2017 at 19:37
0
\$\begingroup\$

Perl 6, 246 bytes

my&f={.grep($^a)};my&s=->{.say};$_=[(1..20).pick xx(5..10).pick];s;$_»--
if f 7;s;$_»++ if f 0;s;.splice(.first(13):k//+$_);s;$_=[f*%%2]if f 2;
s;say(20*(.[2]%%2||$_)),exit if $_>2&&f 20;s;.pop while
.sum>49;$/=f 16;$_=.sum;s;.base(16).say if $/

Ungolfed:

my &f = { .grep($^a) };  # Helper function: search $_ for something
my &s = -> { .say };     # Helper function: print $_
$_ = [ (1..20).pick xx (5..10).pick ];  # Generate the initial array
s;  # Print the array
$_»-- if f 7;  # Decrement all elements if it contains a 7
s;  # Print the array
$_»++ if f 0;  # Increment all elements if a zero is found
s;  # Print the array
.splice(.first(13):k // +$_);  # Splice out everything from the first 13 onward
s;  # Print the array
$_ = [ f *%%2 ] if f 2;  # Remove all odd elements if a 2 is found
s;  # Print the array
say(20*(.[2] %% 2 || $_)), exit if $_ > 2 && f 20;  # Print and exit, maybe
s;  # Print the array
.pop while .sum > 49;  # Remove elements from the end until sum is below 50
$/ = f 16;  # Save in $/ whether $_ contains a 16
$_ = .sum;  # Set $_ to its own sum
s;  # Print the sum
.base(16).say if $/  # Print the sum in hexadecimal if the last array contained a 16
\$\endgroup\$
0
\$\begingroup\$

Common Lisp, 490 bytes

Here the array is represented as a Common Lisp list.

(let((a(loop for i from 1 to(+ 5(random 5))collect(1+(random 19)))))(flet((p()(format t"~a~%"a))(m(x)(member x a))(h(x)(map-into a x a)))(p)(and(m 7)(h'1-))(p)(and(m 0)(h'1+))(p)(let((p(position 13 a)))(and p(setf a(butlast a (-(length a)p)))))(p)(and(m 2)(setf a(remove-if'oddp a)))(p)(or(and(m 20)(or(and(third a)(oddp(third a))(* 20(length a)))20))(p)(and(setf a(loop for x in a sum x into s while (<= s 50) collect x)) nil)(p)(let((s(reduce'+ a)))(print s)(and(m 16)(format t"~x"s))))))

As usual, large use of and and or as control structures.

(let ((a (loop for i from 1 to (+ 5 (random 5))  ; create initial list
            collect (1+ (random 19)))))
  (flet ((p () (format t "~a~%" a))     ; auxiliary functions: print list
         (m (x) (member x a))           ; check membership
         (h (x) (map-into a x a)))      ; operate on elements
    (p)
    (and (m 7) (h '1-))                 ; if 7 is present decrement all values
    (p)
    (and (m 0) (h '1+))                 ; if 0 is now present increment all values
    (p)
    (let ((p (position 13 a)))          ; remove from 13 (if exists)
      (and p (setf a (butlast a (- (length a) p)))))
    (p)
    (and (m 2) (setf a (remove-if 'oddp a)))   ; if 2 is present remove odd values
    (p)
    (or (and (m 20)                            ; if 20 is present
             (or (and (third a)                ;    when third is present
                      (oddp (third a))         ;         and it is odd
                      (* 20 (length a)))       ;         return 20 times the length
                 20))                          ;    otherwise return 20
        (p)                                    ; otherwise (20 is not present)
        (and (setf a (loop for x in a sum x into s ; compute sum of elements
                        while (<= s 50)            ; limited to 50
                        collect x))                ; and return those elements
             nil)                                  ; (to execute the rest of the code)
        (p)
        (let ((s (reduce '+ a)))                   ; compute the final sum
          (print s)                                ; print the result in decimal
          (and (m 16) (format t "~x" s))))))       ; if 16 is present print also in hexadecimal
\$\endgroup\$
0
\$\begingroup\$

Perl 5 -MList::Util=sum, 256 bytes

$,=$";say$_="@{[map{0|1+rand 20}1..5+rand 6]}";/\b7/&&s/\d+/$&-1/ge&&(say)&&/\b0/&&s/\d+/$&+1/ge&say;s/ ?13.*//&&say;@a=/\d+/g;/\b2\b/&&say@a=grep$_%2-1,@a;/20/&&(say$a[2]%2?20*@a:20)&exit;$t=pop@a while($_=sum@a)>50;$t&&say@a;say;"@a"=~/16/&&printf"%x",$_

Try it online!

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

Vyxal, 82 bytes

6℅4+ƛ20℅;…:7c[‹…:A¬[›…}1J:13ḟẎ…:2cß~₂…D20c[2i₂[20|L20*],Q}1J:¦‡50>ǑẎ…:16c[∑₌,H,|∑,

Try it Online!

Explained

6℅4+ƛ20℅;…:7c[‹…:A¬[›…}1J:13ḟẎ…:2cß~₂…D20c[2i₂[20|L20*],Q}1J:¦‡50>ǑẎ…:16c[∑₌,H,|∑,
6℅4+ƛ20℅;…  # Generate the original array with randint(1, 6) + 4 items, each being randint(1, 20). Print it without popping.
:7c[‹…      # If the array contains a 7, subtract 1 from everything
:A¬[›…}     # If there's 0s after doing that, add 1 to everything
1J:13ḟẎ…    # Find the first occurance of `13` in the array with a 1 appended, and keep everything up to that index. If `13` is not in the array, this will return -1, and will keep everything except the appended 1. Basically, the appended 1 is always removed.
2cß~₂…      # If the array contains a 2, keep only even numbers
D20c[2i₂[   # If there's 20 in the array and the 3rd item (0 if < 3 items) is even:
20          #   Push 20
|L20*       # else, push len(array) * 20
,Q}         # print and terminate
1J:¦‡50>ǑẎ… # find the first item in the cumulative sums of the array where the sum is > 50 and keep until that index. Same logic as the 13 check.
:16c[       # If 16 is in the array
∑₌,H,       # Print the sum as dec and hex
|∑,         # else, just print the sum
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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