12
\$\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\$
  • 1
    \$\begingroup\$ How random does "random" have to be? \$\endgroup\$ – HyperNeutrino Apr 13 '17 at 4:21
  • 1
    \$\begingroup\$ @HyperNeutrino it can be as sudo-random as you want, but not challenge throwing. Repeats are allowed. \$\endgroup\$ – Graviton Apr 13 '17 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\$ – Qwerp-Derp Apr 13 '17 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\$ – Greg Martin Apr 13 '17 at 6:11
  • 2
    \$\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 Apr 13 '17 at 9:54

16 Answers 16

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\$
  • \$\begingroup\$ All checks out to me, thanks for being honest. \$\endgroup\$ – Graviton Apr 13 '17 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 Apr 13 '17 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 Apr 15 '17 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\$ – HyperNeutrino Apr 18 '17 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\$ – Zacharý Jun 14 '17 at 14:49
7
\$\begingroup\$

Javascript (ES6), 344 342 340 342 335 331 333 313 311 305 298 297 290 289 283 279 bytes

Huzzah! Finally tied with beat Arnauld!

Following this exchange* in the challenge's comments and after much deliberation I have decided 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.

_=>(l=alert,r=new Date,l(a=[...Array(r%6+5)].map(x=>r%20+1)),i=v=>~a.indexOf(v),i(7)&&l(a=a.map(x=>--x)),i(0)&&l(a=a.map(x=>++x)),i(13)&&l(a=a.slice(0,~i(13))),i(2)&&l(a=a.filter(x=>x%2)),i(t=20)?a[2]%2?t*a.length:t:l(a=a.filter(x=>s+x<51?s+=x:0,s=0))|i(16)?[s,s.toString(16)]:s)

Try it

f=
_=>(l=alert,r=new Date,l(a=[...Array(r%6+5)].map(x=>r%20+1)),i=v=>~a.indexOf(v),i(7)&&l(a=a.map(x=>--x)),i(0)&&l(a=a.map(x=>++x)),i(13)&&l(a=a.slice(0,~i(13))),i(2)&&l(a=a.filter(x=>x%2)),i(t=20)?a[2]%2?t*a.length:t:l(a=a.filter(x=>s+x<51?s+=x:0,s=0))|i(16)?[s,s.toString(16)]:s)
alert(f())

  • Saved 2 bytes by only logging the popped elements in rule 6.
  • Saved 2 bytes by replacing Array(x).fill() with [...Array(x)].
  • Added 2 bytes 'cause I'd messed up on rule 5!
  • Saved 7 bytes fixing the mess I made trying to fix the previous mess!
  • Saved 3 bytes thanks to Arnauld helping me cure a brainfart on rule 2 and saved an additional byte by replacing a +1 with a ~.
  • Added 2 bytes ensuring 0 is returned for an empty array.
  • Saved 20 bytes by finally figuring out how to ditch that fecking while loop.
  • Saved 2 bytes by replacing the , between the last 2 statements with a | and removing the enclosing ().
  • Saved 6 bytes by replacing console.log with alert.
  • Saved 7 bytes by improving the shortcutting of a.includes().
  • Saved 1 byte by editing the implementation of rule 3.
  • Saved 7 bytes by ditching includes() and just using indexOf() throughout.
  • Saved 1 byte by moving the initial declaration of the s variable to somewhere it didn't need a comma.
  • Saved 6 bytes by replacing Math.random() with new Date.
  • Saved 4 bytes by removing the (now redundant) rounding of the random numbers.

Readable & Testable version

  • Added line breaks & comments to code
  • Used console.log instead of alert for your sanity! (Best viewed in your browser's console)
  • Added the current rule number to the output.
  • Commented out random array generation to allow testing by input of a comma separated list of numbers.

f=a=>(
    // Alias alert as l
    // (console.log used for this demo)
    l=(s,a)=>console.log(s+JSON.stringify(a))/*alert*/,
    // Alias new Date as r
    r=new Date,
    // Initiate an array of random length
    // Destructure array
    // Map a random value to each array element
    // (Above all commented out to allow testing your own arrays)
    // Log the initial array
    l("Initial: ",a/*=[...Array(r%6+5)].map(x=>r%20+1)*/),
    // Assign a.indexOf to shortcut i
    i=v=>~a.indexOf(v),
    // Check for the presesnce of 7
    // Invoke the first rule, decrementing the value of each element by 1
    // Log the resulting array
    i(7)&&l("Rule 1: ",a=a.map(x=>--x)),
    // Check for the presesnce of 0
    // Invoke the second rule, incrementing the value of each element by 1
    // Log the resulting array
    i(0)&&l("Rule 2: ",a=a.map(x=>++x)),
    // Check for the presence of 13
    // Invoke the third rule, slicing the array to the index of 13
    // Log the resulting array
    i(13)&&l("Rule 3: ",a=a.slice(0,~i(13))),
    // Check for the presence of 2
    // Invoke the fourth rule, removing all elements whose value have a remainder when divided by 2
    // Log the resulting array
    i(2)&&l("Rule 4:",a=a.filter(x=>x%2)),
    // Assign 20 to variable t
    // (Note: this does not yet save any bytes, but it doesn't cost any either)
    // Check for the presence of 20
    // Invoke the fifth rule, returing 20 times the array length ...
    // ... if the third element (2 in a 0 based index) leaves a remainder when divided by 2 ...
    // ... or just 20, if not
    i(t=20)?"Rule 5: "+(a[2]%2?t*a.length:t):
    // Assign the sum of the array to variable s
    // Invoke the sixth rule by filtering through the array, ...
    // ... adding the value of each element to s, as long as the result is less than 51 ...
    // ... otherwise remove the element from the array
    // Log the current array
    l("Rule 6 :",a=a.filter(x=>s+x<51?s+=x:0,s=0))|
    // Check for the presence of 16
    // If present, invoke the seventh rule, returning the sum and its hex value (as an array)
    // Otherwise simply return the sum
    i(16)?"Rule 7: "+[s,s.toString(16)]:"Sum: "+s
);

document.querySelector`button`.addEventListener(`click`,_=>(console.clear(),console.log(f(document.querySelector`input`.value.split`,`.map(eval)))))
<input><button>Test</button>


*Screenshot, in case it's deleted:

\$\endgroup\$
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\$
  • \$\begingroup\$ 84 bytes, and potentially correct? Different? No idea. tio.run/nexus/… \$\endgroup\$ – Magic Octopus Urn Apr 14 '17 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 Apr 16 '17 at 8:14
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\$
  • 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\$ – Kevin Cruijssen Apr 13 '17 at 14:34
  • \$\begingroup\$ Ok, found something for -3 bytes ;p \$\endgroup\$ – Kevin Cruijssen Apr 13 '17 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\$ – HyperNeutrino May 13 '17 at 2:44
  • \$\begingroup\$ @HyperNeutrino Golfed off another 2 bytes \$\endgroup\$ – cleblanc May 15 '17 at 12:50
  • \$\begingroup\$ Yay! Nice job :D \$\endgroup\$ – HyperNeutrino May 15 '17 at 12:51
3
\$\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\$
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\$
  • \$\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 Apr 13 '17 at 20:08
  • 1
    \$\begingroup\$ @Shaggy That's correct. But you can't get a zero unless rule 1 is triggered. \$\endgroup\$ – Arnauld Apr 13 '17 at 21:34
  • \$\begingroup\$ D'oh! Of course! Man, I've been having a ridiculous number of brainfarts during this challenge :( \$\endgroup\$ – Shaggy Apr 13 '17 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 Apr 14 '17 at 13:09
  • 1
    \$\begingroup\$ @Shaggy Ahah! Nice job! \$\endgroup\$ – Arnauld May 5 '17 at 17:30
2
\$\begingroup\$

Java 7, 622 619 618 bytes

import java.util.*;void c(){Random r=new Random();List<Long>l=new ArrayList();int i=0,c=r.nextInt(6)+5;for(;i++<c;l.add(r.nextInt(20)+1L));p(l);if(l.contains(7)){for(i=0;i<c;l.set(i,l.get(i++)-1));p(l);}if(l.contains(0)){for(i=0;i<c;l.set(i,l.get(i++)+1));p(l);}if((i=l.indexOf(13))>=0){for(;i<l.size();l.remove(i));p(l);}if(l.contains(2)){for(i=0;i<l.size();)if(l.get(i)%2>0)l.remove(l.get(i));else i++;p(l);}if(l.contains(20)){p(20*(l.get(2)%2<1?1:l.size()));return;}i=0;for(long x:l)i+=x;for(;i>50;)i-=l.remove(l.size()-1);p(l);if(l.contains(16))p(Byte.valueOf(i+"",16));p(i);}<T>void p(T t){System.out.println(t);}

-1 byte thanks to @Poke

Explanation:

import java.util.*;                      // Imports used for List, ArrayList and Random

void c(){                                // Main method
  Random r=new Random();                 //  Random generator
  List<Long>l=new ArrayList();           //  The list
  int i=0,                               //  Temp index we use multiple times
      q=r.nextInt(6)+5;                  //  Random size of the list (5-10)
  for(;i++<q;l.add(r.nextInt(20)+1L));   //  Fill the list with random long-integers (1-20)
  p(l);                                  //  Print the initial list
  if(l.contains(7)){                     //  If the list contains a 7
    for(i=0;i<c;l.set(i,l.get(i++)-1));  //   Decrease each number in the list by 1
    p(l);                                //   And then print the list again
  }                                      //  End of if
  if(l.contains(0)){                     //  If the list now contains a 0
    for(i=0;i<c;l.set(i,l.get(i++)+1));  //   Increase each number in the list by 1
    p(l);                                //   And then print the list again
  }                                      //  End of if
  if((i=l.indexOf(13))>=0){              //  If the list contains a 13 (and save it's index in `i` at the same time)
    for(;i<l.size();l.remove(i));        //   Remove everything from that index and onward
    p(l);                                //   And then print the list again
  }                                      //  End of if
  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 list item is odd
        l.remove(l.get(i));              //     Remove it
      else                               //    If it's even instead
        i++;                             //     Go to the next item
                                         //   End of loop (implicit / single-line body)
    p(l);                                //   And print the list again
  }                                      //  End of if
  if(l.contains(20)){                    //  If the list now contains a 20
    p(20*(l.get(2)%2<1?1:l.size()));     //   Print 20 if the third item in the list is odd, or 20*size if it's even instead
    return;                              //   And then terminate the method
  }                                      //  End of if
  i=0;                                   //  Reset `i` to 0
  for(long x:l)i+=x;                     //  And calculate the total sum of the list (stored in `i`)
  for(;i>50;)                            //  Loop as long as this list's sum is above 50
    i-=l.remove(l.size()-1);             //   Subtract the last item from this sum, and then remove it from the list
                                         //  End of loop (implicit / single line body)
  p(l);                                  //  And print the list again
  if(l.contains(16))                     //  If the list now contains a 16
    p(Byte.valueOf(i+"",16));            //   Print the sum (still stored in `i`) as hexadecimal
                                         //  End of if (implicit / single-line body)
  p(i);                                  //  And print the sum as integer either way
}                                        // End of main method

<T>void p(T t){                          // Separate method with a generic parameter
  System.out.println(t);                 //  Print the given parameter including a new-line
}                                        // End of separated method

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

Try it here.

[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\$
  • 1
    \$\begingroup\$ I'm down to 594 bytes now :-D \$\endgroup\$ – cleblanc Apr 13 '17 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\$ – Kevin Cruijssen Apr 14 '17 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 Apr 14 '17 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 Apr 18 '17 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\$ – Kevin Cruijssen Apr 19 '17 at 6:45
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\$
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\$
1
\$\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\$
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\$
  • \$\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\$ – Sriotchilism O'Zaic Apr 14 '17 at 2:29
  • \$\begingroup\$ I added the one line low byte version \$\endgroup\$ – Saideep Sambaraju Apr 17 '17 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\$ – Zacharý Jun 13 '17 at 19:26
  • \$\begingroup\$ no I think I missed it. \$\endgroup\$ – Saideep Sambaraju Jun 13 '17 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\$
  • \$\begingroup\$ I don't think you need the space between the and and ~. \$\endgroup\$ – Zacharý Jun 14 '17 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 Jun 16 '17 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\$

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.