Make big rocks into small rocks

22

2

Welcome to the grinder.

Your task is to make big rocks into small rocks by grinding them.

Take an input of a big rock of size n > 3 and grind it.

Continue to grind the rocks by dumping them into the grinder until the size of all the rocks are 2.

rocks are always grinded into equal even halves. If the result of a grinding is odd take result - 1.

Print the output of each grinding as you proceed.

Examples

input: 5

output: 22

The result are two rocks of size 2

input: 50

output:

2424 //two rocks of size 24
12121212 //four rocks of size 12
66666666 //8 rocks of size 6
2222222222222222

the result is 16 rocks of size 2

input: 30

output:

1414
6666
22222222

the result is 8 rocks of size 2

This is so the shortest code wins! Have fun and good luck!

jacksonecac

Posted 2016-12-02T12:52:56.370

Reputation: 2 584

You can expect it to be above 3. – jacksonecac – 2016-12-02T13:33:02.827

Do we have to use your format (all numbers concatenated) or can we use things like lists? Some answers seem to do that instead. – Fatalize – 2016-12-02T14:01:02.413

As long as the output displays each iteration the format does not need to be like above. – jacksonecac – 2016-12-02T14:03:21.080

...does that go as far as being allowed to output he input too? e.g. for input 50 could output be [50, [24, 24], [12, 12, 12, 12], [6, 6, 6, 6, 6, 6, 6, 6], [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]]? – Jonathan Allan – 2016-12-02T14:07:08.347

@JonathanAllan a single array is fine, a 2d array doesnt really fit the requirements. – jacksonecac – 2016-12-02T14:09:52.047

1I would say a 2d array does and a 1d does not , but it's up to you so OK. – Jonathan Allan – 2016-12-02T14:15:04.533

@JonathanAllan just answer the dang question :P – jacksonecac – 2016-12-02T14:16:54.253

Can we assume input will always be <100? <256? – undergroundmonorail – 2016-12-02T14:21:50.463

is it a program, or function? is initial number should be read from stdin or can be passed as argument? – user902383 – 2016-12-02T17:54:42.360

1

@user902383 either is fine unless specified in the challenge as per meta consensus. As for input and output, again both are fine - see this post.

– Jonathan Allan – 2016-12-02T20:17:09.747

Answers

12

TSQL, 61 59 bytes

DECLARE @ int=50

,@x int=1WHILE @>2SELECT @=@/4*2,@x*=2PRINT replicate(@,@x)

Try it out

t-clausen.dk

Posted 2016-12-02T12:52:56.370

Reputation: 2 874

8

COW, 297 291 bytes

MoOMoOMoOMoOMoOMoOMoOMoOMoOMoOmoOMoOmoOmoOoommOoMoOMOOmoOMMMmoOMMMmoOOOOMoOmOoMOOMOomoOmoO
MOOMOomOoMOomoOmoomOoMMMOOOMoOmoOMMMmOomOomoomoOmoOMOOMOomOomOomOoMOomoOmoOmoOmoomOomOomOo
mOomOoMMMmoOMMMMOOMOomoOOOMmOomOoMoOmoOmoomOomOoMoomoOmoOmoOMOOMOoMOomoOMoOmOomoomoOMMMOOO
mOoMMMMMMmOoMMMMOomoo

Try it online!

The code prints each number on its own line, and separates iterations with an additional newline. It also prints the first iteration by itself, followed by a newline. So an input of 5 would give an output that looks like 5 2 2 except with newlines instead of spaces. Sample output for 50 is given below.

Explanation tree:

MoOMoOMoOMoOMoOMoOMoOMoOMoOMoOmoOMoOmoOmoOoom ;Store 10 in [0], 1 in [1], and integer input in [3]
mOoMoO                                        ;Store 1 in [2]
MOO                                           ;Loop while [2] is non-zero
   moOMMMmoOMMMmoOOOOMoOmOo                   ;   Copy [3] to [4], clear contents of [5], and store 1 in [5]
   MOO                                        ;   Loop while [4] is non-zero
      MOomoOmoO                               ;      Decrement 4 and move to 6
      MOO                                     ;      Loop while [6] is non-zero
         MOomOoMOomoO                         ;         Decrement [5] and [6]
      moo                                     ;      End loop once [6] is empty
      mOoMMMOOOMoOmoOMMMmOomOo                ;      Copy [5] to [6], and reset [5] to 1, then move back to [4]
   moo                                        ;   End loop now that [4] is empty.  [6] now contains the parity of [3]
   moOmoO                                     ;   Navigate to [6]
   MOO                                        ;   Loop while [6] is non-empty
      MOomOomOomOoMOomoOmoOmoO                ;      Decrememnt [3] and [6]
   moo                                        ;   End loop now that [6] is empty.  [3] now contains the largest even number less than the previous iteration.
   mOomOomOomOomOoMMMmoOMMM                   ;   Copy [1] to [2]
   MOO                                        ;   Loop while [2] is non-empty
      MOomoOOOMmOomOoMoOmoO                   ;      Decrement [2], increment [1], and print the number in [3].
   moo                                        ;   End loop now that [2] is empty
   mOomOoMoo                                  ;   Print a new line
   moOmoOmoO                                  ;   Navigate to [3]
   MOO                                        ;   Loop while [3] is non-empty
      MOoMOomoOMoOmOo                         ;      Decrement [3] twice and increment [4] once
   moo                                        ;   [4] now contains half of [3]
   moOMMMOOOmOoMMM                            ;   Copy [4] to [3] and clear [4]
   MMMmOoMMMMOo                               ;   Copy [3] to [2] and decrement once
moo                                           ;End loop now that [2] is empty

Sample output for input 50:

50

24
24

12
12
12
12

6
6
6
6
6
6
6
6

2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2

Gabriel Benamy

Posted 2016-12-02T12:52:56.370

Reputation: 2 827

2I have no words – jacksonecac – 2016-12-05T12:11:26.360

I still have no words – jacksonecac – 2016-12-19T12:15:51.940

I don't have any words – Edeki Okoh – 2019-05-09T23:45:42.133

I love how two and a half years later, this still horrifies people. – Gabriel Benamy – 2019-05-11T00:08:50.220

7

05AB1E, 12 11 bytes

¸[4÷·€D=¬<#

Try it online!

Explanation

¸             # wrap input in a list
 [            # start infinite loop
  4÷          # elementwise integer divison by 4
    ·         # elementwise multiplication by 2
     €D       # duplicate each element in the list
       =      # print it
        ¬     # get the first element of the list
         <    # decrease it by 1
          #   # if true: exit loop

Emigna

Posted 2016-12-02T12:52:56.370

Reputation: 50 798

6

Python 2, 55 53 bytes

n=input()
while n[0]>2:n=len(n)*2*[n[0]/4<<1];print n

Divide by 4 and left shift by 1 to get the special division

Rod

Posted 2016-12-02T12:52:56.370

Reputation: 17 588

4

Haskell, 75 71 60 50 47 bytes

f 0=[]
f n|x<-f$2*div n 4=show n:zipWith(++)x x

Try it online! Edit: As the output is now allowed to be a list including the input, 10 13 bytes can be saved.

Usage:

Prelude> f 50
["50","2424","12121212","66666666","2222222222222222"]

Original 60 byte version:

2%x=""
n%x|z<-2*div n 4=([1..x]>>show z)++"\n"++z%(x*2)
(%2)

Try it online! Thanks to Christian Sievers for pointing out the shorter formula.

Usage:

Prelude> (%2)50
"2424\n12121212\n66666666\n2222222222222222\n"

Laikoni

Posted 2016-12-02T12:52:56.370

Reputation: 23 676

You can just do z<-2*div n 4. – Christian Sievers – 2016-12-02T17:00:46.130

3

Python 2, 48 47 bytes

s=input()
n=1
while s>3:s=s/4*2;n*=2;print`s`*n

TFeld

Posted 2016-12-02T12:52:56.370

Reputation: 19 246

s=s/4*2 will work for 1 byte save. – Jonathan Allan – 2016-12-02T13:50:56.530

3

JavaScript (ES6) 64 59 57 Bytes

f=s=>{for(n=1;s>2;)console.log(`${s=s/4<<1}`.repeat(n*=2))}

console.log(f.toString().length); 
f(5);
f(50);
f(30);                                  

Lmis

Posted 2016-12-02T12:52:56.370

Reputation: 421

if I put your code into https://mothereff.in/byte-counter I get 59 bytes?

– Tschallacka – 2016-12-03T09:40:33.770

@Tschallacka I think the f= but is just for the demo – LarsW – 2016-12-03T11:58:20.277

Ah, okay. That makes it clear :-) still gotta get 2 bytes off myne then – Tschallacka – 2016-12-03T12:19:45.977

3

C#, 88 86 83 bytes

Saved 3 bytes thanks to Skorm

Saved another byte by changing the while to a for loop which includes variable declarations

Saved 1 bytes thanks to Yodle

n=>{var r="";for(int i,c=2;n>2;c*=2,r+="\n")for(i=0,n=n/4*2;i++<c;)r+=n;return r;};

Anonymous function which returns a string composed of the result of each grinding.

Full program with ungolfed method and test cases [before the last edit!]:

using System;

public class Program
{
    public static void Main()
    {
        Func<int, string> f =
        n =>
        {
            var r = "";
            for (int i, c = 1; n > 2; )  // iterator and counter variable
            {
                    n = n/4 * 2;    // make sure the result if even
                    c *= 2;         // keep track of the number of rocks
                    for (i = 0; i++ < c; )  // store the current line made of [c] rocks of size [n]
                        r += n;
                    r += "\n";      // add a trailing newline to the string resulted from this step
            }
            return r;       // return the entire history
        };

        //test cases:
        Console.WriteLine(f(5));
        Console.WriteLine(f(50));
        Console.WriteLine(f(30));
    }
}

adrianmp

Posted 2016-12-02T12:52:56.370

Reputation: 1 592

2Think you can save 1 byte in the for loop by doing for(i=0;i++<c;) – Yodle – 2016-12-02T15:03:28.990

You can still save 1 byte, as yoddle mentioned by changing your second for to for (i = 0; i++ < c;) – MX D – 2016-12-02T15:54:14.217

Forgot to update the post. Updated now :) – adrianmp – 2016-12-02T16:02:52.990

1You can update your counter to start at 2 and *=2 each iteration to save 1 byte, and move the new line append. You can then move the n = n / 4 * 2 into the second loop and remove the braces to save 2 more.

n=>{var r="";for(int i,c=2;n>2;c*=2,r+="\n")for(i=0,n=n/4*2;i++<c;)r+=n;return r;} – Skorm – 2016-12-02T17:05:56.463

3

Java, 85 bytes

n->{String s="";for(int q=2,i;n>2;q*=2,s+="\n")for(i=q,n=n/4*2;i-->0;)s+=n;return s;}

Testing and ungolfed

import java.util.function.*;

class Ideone {
  public static void main(String[] args) throws java.lang.Exception {
    Function<Integer, String> f = number -> {
      String result = "";
      for (int quantity = 2, i; number > 2; quantity *= 2) {
        number = number / 4 * 2; // Make sure that the next is half or half - 1 if odd
        for (i = quantity; i > 0; i--) { // copy "quantity" times.
          result += number;
        }
        result += "\n"; // append new line
      }
      return result;
    };
    System.out.println(f.apply(50));
  }
}

Note: I don't know why, Ideone keeps giving internal error, so testing on it is a problem. To test, just copy/paste and run in your standard Java IDE. (It works there, I made sure of it ;) )

Olivier Grégoire

Posted 2016-12-02T12:52:56.370

Reputation: 10 647

ideone works fine with your code. It's somtimes giving an internal error when they are doing maintenance (I think). I've had it before when I looked back at old answers of mine. +1 btw, I don't see anything that can be golfed more. Oh, and I like your n=n/4*2 trick. :) – Kevin Cruijssen – 2016-12-14T11:44:07.573

2

CJam, 21 bytes

l~]{{2/-2&_}%_n_2-}g;

Try it online! (As a test suite.)

Explanation

l~]      e# Read input, evaluate and wrap it in a singleton list.
{        e# Do while...
  {      e#   Map this block over the list of rocks.
    2/   e#   Halve the rock.
    -2&  e#   Bitwise AND with -2, clearing the least-significant bit and
         e#   rounding down to an even integer.
    _    e#   Duplicate.
  }%
  _n     e# Print a copy of the current list of rocks.
  _2-    e# Continue if the current list of rocks contains values that aren't 2.
}g
;        e# Discard the final result to prevent printing it again.

Martin Ender

Posted 2016-12-02T12:52:56.370

Reputation: 184 808

2

Jelly, 13 12 11 bytes

:4Ḥx2µȦпṖY

TryItOnline!

Note: the OP stated that the input may also be in the output.

How?

:4Ḥx2µȦпṖY - Main link: rockSize
     µ      - monadic separation
       п   - loop collect intermediate results while
      Ȧ     - any
:4          -     integer division (vectorises) by 4
  Ḥ         -     double (vectorises)
   x2       -     repeat the elements 2 times
         Ṗ  - pop (remove the trailing list of zeros)
          Y - join with line feeds

Version without the input displayed for 12 bytes: :4Ḥḟ0x2µÐĿḊG

Jonathan Allan

Posted 2016-12-02T12:52:56.370

Reputation: 67 804

2

Pyth, 18 16 13 bytes

WhQ=Q*2my/d4\n

* \n is a new line
Explanation :

W              # While
 hQ            # first element of Q - 0 is falsy
   =Q          # assign to Q
     *2        # the double of the (list) that is returned
       m       # form this \/ map
         /d4   # divide every element by 4
        y      # and double
            \n # print Q

Try here

Rod

Posted 2016-12-02T12:52:56.370

Reputation: 17 588

2

PHP, 72 67 64 bytes

for($n=$argv[$k=1];$n>2;)echo str_repeat($n=$n/2&~1,$k*=2),"\n";

Takes argument from command line. Run with -r.

Titus

Posted 2016-12-02T12:52:56.370

Reputation: 13 814

2

MATL, 13 bytes

`K/kEthttH>]x

Try it online!

`       % Do...while
  K/k   %   Divide by 4 and round down. Takes input implicitly in the first iteration
  E     %   Multiply by 2
  th    %   Attach a copy of itself (creates a longer array)
  t     %   Duplicate. This copy will be used for further grinding, keeping the original
  tH>   %   Duplicate. True if the values exceed 2. Used as loop condition
]       % End. The loop exits if the latest array contains 2
x       % Delete last copy. Implicitly display the entire stack

Luis Mendo

Posted 2016-12-02T12:52:56.370

Reputation: 87 464

2

Perl, 40 35 30 + 1 = 31 bytes

Run with the -n flag

-4 bytes thanks to @Dada

say$_ x($.*=2)while$_=$_>>1&~1

Try it online!

Perl automatically reads the input into the variable $_ when -n is set. $. is a special variable set to 1 at the beginning of the program by the interpreter, so I can use it as a base for doubling. Every iteration of the while loop, it bit-shifts $_ down and performs a logical AND against the negative of itself minus one to cancel out the ones bit.

Gabriel Benamy

Posted 2016-12-02T12:52:56.370

Reputation: 2 827

You can golf it down to 31 bytes : perl -nE 'say$_ x($.*=2)while$_=$_>>1&~1' (maybe this can be golfed even further, I didn't spent a lot of time on it). – Dada – 2016-12-02T19:04:50.747

2

PowerShell 3+, 58 54 bytes

for($s=$input;$s;$s=($s-shr2)*2){"$s"*(2-shl($i++)-1)}

Thanks TimmyD for saving me 4 bytes!

Slightly Ungolfed (formatting)

for ( $s = $input ; $s ; $s = ( $s -shr 2 ) * 2 ) {
    "$s" * (2 -shl ($i++)-1)
}

Explanation

I'm using the same divide by 4 multiply by 2 trick as a lot of the other answers, but I ran into a problem. PowerShell converts numbers to floating point if needed during division, and for golfing that's annoying because $v/4*2 becomes something unsighlty like [int]($v/4)*2. I got around that using bitshifting for the division with -shr.

For calculating how many times to print an iteration I just take (2^$i)-1 which works nicely and has the added effect of leaving out the input value. Trying to just multiply by 2 was problematic because starting from 0 makes it hard to increase the value with just $i*=2 and starting from 1 requires too much correction to get the number right.

Since PowerShell doesn't have an operator for it, and I wanted to avoid [Math]::Pow(), I relied on bitshifting again for my powers of 2.

briantist

Posted 2016-12-02T12:52:56.370

Reputation: 3 110

@TimmyD whoops forgot to mention version, and good tip; thanks! – briantist – 2016-12-05T19:35:53.763

1

Python 2, 47 Bytes

Since the OP said that a 1D array which included the input was fine I have come up with this recursive function, which unfortunately only ties with the current Python winner.

f=lambda s,n=1:[s]*n+(f(s/4*2,n*2)if s>3else[])

Kade

Posted 2016-12-02T12:52:56.370

Reputation: 7 463

f=lambda r,n=1:[r]*n+(r>3and f(r/4*2,n*2)or[]) for 46 – Jonathan Allan – 2016-12-02T20:09:30.270

1

Vim 61 54 bytes

qqYpPJ0yw:s;\d*;="/2
;g
:let @t=(">7)+1
@tkjjG@qq@q

TryItOnline!

Unprintables:

qqYpPJ0yw:s;\d*;^R=^R"/2
;g
:let @t=(^R">7)+1
@tkjjG@qq@q

Luckily vim automatically truncates on x/2.

nmjcman101

Posted 2016-12-02T12:52:56.370

Reputation: 3 274

1

Perl, 47 bytes

$a=<>>>1;say 2*(($a>>=1)||die)x(1<<$_)for 1..$a

No command-line options, this time (unusually for Perl). The basic idea is that as all the rocks at any given step are the same size, we just record the size (in $a) and the number (in $_), rather than recording the whole list. I couldn't find a way to get rid of the space (or +) after say; you can move the 2* but it won't parse correctly if it's followed by an opening parenthesis.

I can't help but shake the feeling that this is improvable, but I can't see how.

user62131

Posted 2016-12-02T12:52:56.370

Reputation:

If I try to golf it to much, I end up with Gabriel Benamy's answer every time. Just to show a few steps: the die clearly feels sub-optimal. But we still need a way to check if we need to stop or not -> a solution is to use a while instead of the for: while$a>1. But we need to find a replacement for $_: any unitialized variable can do it: replace 1<<$_ by 1<<++$x. So now $_ is free to be used, we can then use -n and replace every $a with a $_, and the first instruction becomes $_>>=1. Since we have -n, $. is set, so we can replace 1<<++$l with $.*=2. – Dada – 2016-12-02T22:17:34.213

Doing all those modifications will produce perl -nE '$_>>=1;say 2*($_>>=1)x($.*=2)while$_>1' (39 bytes). Then notice that $_>>=1 is done twice, so we can try to get rid of one (the first one). Trying to get rid of it, I got say$_ x($.*=2)while($_>>=1)/2>1 (put both of them inside the while condition). But the result is wrong ($_ can be odd), and trying to make sure it's even, I end up with while$_=$_>>1&~1. So the code is now say$_ x($.*=2)while($_=$_>>1&~1). – Dada – 2016-12-02T22:18:22.590

I missed that there was a Perl answer already. I guess if golfing this down turns it into a duplicate, there's not much point in editing it. On the other hand, it's not actually wrong, so there's not much point in deleting it either. We're probably best off just leaving it as a testament to my inferior Perl golfing powers. – None – 2016-12-02T22:36:22.373

I agree, it's different enough from the other Perl solution, and with my previous comments, I tried to show that the only way I could golf it would turn it into the other solution. So leaving it as it is feels like the right solution. – Dada – 2016-12-02T22:39:11.103

1

JavaScript, 71 63 59 58 Bytes

Well, I came up with this javascript solution. Totally new at golfing, but I foudn this a fun challenge

Saved 4 bytes thanks to Titus suggestion using a for loop.

ungolfed basis:

for(o = i = 30; i > 1; i= i/4<<1) {
   console.log(`${i}`.repeat(o / i));
}

Golfed version

for(o=i=30;i>1;i=i/4<<1){console.log(`${i}`.repeat(o/i));}

I'm open for suggestions how to improve it / learn golfing

input tester

function test(a){
var el = document.getElementById('output');
var text = []; 
for(o = i = parseInt(a); i > 1; i= i/4<<1) {
   text.push(`${i}`.repeat(o / i));
}
  el.innerText = text.join('\n');
}
<input type="input" onchange="test(this.value)"><button>run</button>
<pre id="output">
</pre>

Tschallacka

Posted 2016-12-02T12:52:56.370

Reputation: 147

1You can save two bytes with a for loop: for(o=i=30;i>2;console.log(...)){...}. And with combining the two grinding assigments to one, you can remove the braces: i=i/4<<1; (-5). Not sure if i=i/4*2; will do the same. – Titus – 2016-12-03T09:06:06.697

1I bet you haven´t tested that. – Titus – 2016-12-03T12:44:53.860

not yet, had to run from pc to catch my kids – Tschallacka – 2016-12-03T12:48:49.940

1

BASH, 81 bytes

n=$1
h=1
while [ ${n//2} ];do
printf -v s %$[h=h*2]s
echo ${s// /$[n=n/4*2]}
done

Ipor Sircer

Posted 2016-12-02T12:52:56.370

Reputation: 333

1

Swift, 84 Bytes

func g(n:Int){var n=n,i=2;while n>2{n=n/4*2;print(Array(repeating:n,count:i));i*=2}}

Ungolfed

func grind(rockSize: Int) {
    var rockSize = rockSize
    var rockCount = 1

    while rockSize > 2 {
        rockSize = rockSize / 4 * 2
        rockCount *= 2

        let output = Array(repeating: rockSize, count: rockCount)
        print(output)
    }
}

username tbd

Posted 2016-12-02T12:52:56.370

Reputation: 161

1

Befunge, 45 bytes

&1vg0_\:.\v
:\<  ^!:-1<p00:*2\.:*2/4,+55_@#`2

Try it online!

Explanation

&           read the rock size
1           initialise the count
<           start of main loop going right to left

  \         swap the size to the top of the stack
  :2`#@_    if size is not > 2 then exit
  55+,      output a line break
  4/2*      size = size/4*2, i.e. split into even halves
  :.        output the size
  \         swap the count to the top of the stack
  2*        count = count*2
  :00p      save count for later

  <         start of inner loop
    1-      decrement the count
    :!^_    break out of the loop if the count is zero
    \       swap the size to the top of the stack
    :.      output the size
    \       swap the count to the top of the stack
    v       back to the start of the inner loop    

  0g        restore the saved count
  v         back to the start of the main loop

James Holderness

Posted 2016-12-02T12:52:56.370

Reputation: 8 298

1

Javascript, 106 bytes

First code golf, thought I'd have a go. (It's not very good).

for(;i[i.length-1]>3;){for(var x=0;x<i.length;x++)i[x]/=2,i[x]%2===1&&i[x]--;i=i.concat(i),console.log(i)}

Unminified:

while (input[input.length - 1] > 3) {
    for (var x = 0; x < input.length; x++) {
        input[x] /= 2;
        if (input[x] % 2 === 1) input[x]--;
    }
    input = input.concat(input);
    console.log(input);
}

Jack

Posted 2016-12-02T12:52:56.370

Reputation: 131