Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm tired, but I can't seem to fall asleep. Help me count sheep.

Given an input N (positive integer), make N sheep jump over an ascii fence, like the sample below. Only one frame should be displayed at once:

o |-|
──|-|──  0

 o|-|
──|-|──  0

   o
  |-|
──|-|──  0

  |-|o
──|-|──  0

  |-| o
──|-|──  0

o |-|
──|-|──  1

 o|-|
──|-|──  1

   o
  |-|
──|-|──  1

Count should be kept at the lower right side of the 'ground'. Trailing and leading whitespace and newlines are allowed. If your language of choice has difficulty clearing the screen for each frame you can add sufficient newlines to clear the screen - please state how many lines you add for this in your answer. The program should terminate when the N'th sheep is on the fifth floortile.

I need to get up early tomorrow, so shortest code in bytes wins. Please submit a function or complete program. Standard loopholes apply.

share|improve this question
5  
1. Please, it pains me when people use justifications for short code ("I need to get up early tomorrow") 2. How much whitespace do we put between frames? It looks like 1 newline to be, but you may want to state that clearly. – Easterly Irk yesterday
9  
1) take aspirin 2) There may be only 1 frame on screen. These frames here are to demonstrate each state individually and should NOT be visible on 1 screen simultaneously. – steenbergh yesterday
2  
Many languages do not have the option to clear display, in such cases what output should they provide? – Jonathan Allan yesterday
5  
"add sufficient newlines to clear the screen". Isn't that dependent on the size of the output window as well as screen resolution? – Emigna yesterday
3  
According to your example, for N=3 the last frame will contain a sheep at the right end and the counter will still say 2. Is that correct? – Luis Mendo yesterday

14 Answers 14

up vote 13 down vote accepted

MATL, 60 56 53 bytes

:"@qXJx[HKCbO]"7Z"'  |-|  'v'o'@('--|-|--  '  JVhXxXD

The animation with the above code runs very fast. The following version includes a pause to make the animation slower and thus easier to see (not required by the challenge), at the cost of 4 more bytes:

:"@qXJx[HKCbO]"7Z"'  |-|  'v'o'@('--|-|--  '  JVhXxXD.2Y.

Try it at MATL Online! The interpreter is a beta; refresh the page if it doesn't work.

Or see a recording from the offline compiler:

enter image description here

Explanation

:"              % Input N implicitly. Repeat N times
  @q            %   Push iteration index minus 1, that is, from 0 to N-1. This
                %   are the numbers of sheep
  XJx           %   Copy into clipboard J and delete
  [HKCbO]       %   Push array [2 4 7 -2 0]
  "             %   For each value in that array. This loops generates the 5
                %   frames for each number of sheep
    7Z"         %     Push string of 7 spaces
    '  |-|  '   %     Push this string
    v           %     Concatenate vertically. This gives a 2x7 char array
                %     with the upper part of the frame, except the 'o',
                %     which will be now placed in a varying position 
    'o'         %     Push string 'o'
    @           %     Push loop variable, that is, 2, 4, 7, -2 or 0
    (           %     Write 'o' into that position of the 2x7 char array.
                %     The position is interpreated linearly, that is, a single
                %     number is used as index into the 2D array in column-major
                %     order (down, then across). So index 2 is lower-left corner,
                %     index 4 is to the right of that etc. Indexing is
                %     semi-modular (modular for non-positive values). So 0 is
                %     the lower-right corner, and -2 is to the left of that
    '--|-|--  ' %     Push this string
    JV          %     Push current number of sheep converted to string
    h           %     Concatenate horizontally
    Xx          %     Clear screen
    XD          %     Display all stack contents
    .2Y.        %     Pause for 0.2 seconds (optional)
                %   End implicitly
                % End implicitly
share|improve this answer

JavaScript (ES6), 120 124 bytes

f=(n,m=`   2
43|-|10
──|-|── `,s=0)=>n?alert(m.replace(s%5,'o').replace(/\d/g,' ')+' '+(n-1),(++s%5?f(n,m,s):f(n-1,m,0))):''

The last frame computed is showing first. Thanks to this the jump number is n-1
In alert, charaters have different width so it looks like it's broken.

f=(n,m=`   2
43|-|10
──|-|── `,s=0)=>n?alert(m.replace(s%5,'o').replace(/\d/g,' ')+' '+(n-1),(++s%5?f(n,m,s):f(n-1,m,0))):''
;

f(2);//You'll get 10 alert popup


Previous answer:

120 bytes, the jump number is wrong because it starts at 1 instead of 0

f=(n,m=`   2
43|-|10
──|-|── `,s=0)=>n?alert(m.replace(s%5,'o').replace(/\d/g,' ')+' '+n,(++s%5?f(n,m,s):f(n-1,m,0))):''
share|improve this answer
    
@LuisMendo I updated the counter to start at 0. For the bars it's thanks to the font used by alert. I have the same result than chrome with edge, and it's worse with firefox. – Hedi yesterday

JavaScript (ES6), 144 bytes

Clears the output and waits 300ms between each frame:

n=>(F=j=>((c=console).clear(),c.log(`   2
01|-|34
──|-|── `.replace(/\d/g,i=>(j-i)%5?' ':'o')+(j/5|0)),++j<n*5&&setTimeout(`F(${j})`,300)))(j=0)

You can test it here (make sure to open the console).

share|improve this answer

C#, 234 Bytes

using C=System.Console;class P{static void Main(string[]a){for(int n=0;n-1+""!=a[0];++n){foreach(int p in new[]{5,6,3,10,11}){C.Clear();C.Write("    \n  |-|  \n──|-|── ".Remove(p,1).Insert(p,"o")+n);for(var w=3e7;w>0;--w);}}}}
share|improve this answer
    
At a first glance, there's some whitespaces laying around at string[] args and at for (int. Int32.Parse could be int.Parse. – TuukkaX yesterday
    
@TuukkaX Thank You – Jörg Hülsermann yesterday
1  
You can change the name of the class from Program to just P or something – Matias Cicero 23 hours ago
1  
string could be var. The integer in the for loop could be initialized at the same time you parse args[0] to an integer. – TuukkaX 14 hours ago
    
I see you edit the byte count each time it is lowered. However, I recommend keeping around old byte counts (crossed with a line), to keep track of the progress :) – TuukkaX 14 hours ago

Ruby, 83 bytes

->n{(n*5).times{|i|$><<"   c
  |-|  
ab|-|de  #{i/5}
".tr('abcde',' '*(i%5)+'o ')}}

Prints to stdout. Output separated by newlines. Reducing screen height to 3 makes only one image visible at a time.

share|improve this answer

Tcl, 168 bytes

Version using 10-row-high screen. (Replace the 7 below with your screen height in columns minus four.)

set s {0 1 2 3 4 }
for {set n 0} {$n<$argv} {incr n} {foreach x $s {
puts [string repe \n 6][string map [split $s {}] [string map "$x o" {   2
01|-|34
--|-|--  }]]$n}}

That runs really fast, so you can add a pause on line two:

Tcl, 177 bytes

set s {0 1 2 3 4 }
for {set n 0} {$n<$argv} {incr n} {foreach x $s {after 250
puts [string repe \n 6][string map [split $s {}] [string map "$x o" {   2
01|-|34
--|-|--  }]]$n}}

It works by reusing the string at the top for two different things:

  • as a list for the inner loop (to display each version of the sheep+fence)
  • as a mapping of digit→space to remove digits from the sheep+fence image template

The template itself is the string image to display. First we map (string replace) the sheep's current position digit (inner loop) to an 'o'. Then we map the remaining digits to spaces. Then we print the resulting string.

(The string itself starts after the last { on the third line and ends with the leftmost } on the last line.)

share|improve this answer

05AB1E, 66 60 59 bytes

FNU5Fð4×N<i¨'oJ},N<iðë'o}ðNÉis}"|-|  "JN1›iR},…──|Â'-sððXJ,

Uses CP-1252 encoding.

Explanantion

Iteration refers to the inner iteration (0 -> 4) of the sheeps journey.

Main loops

F      # For N in range [0 .. input)
 NU    # Save N in variable X
 5F    # For N in range [0 .. 5)

Generate top row

ð4×         # push 4 spaces
N<i    }    # if we're on the 2nd iteration
   ¨'oJ     # replace the last space with an "o"
,           # print row

Generate middle row

N<iðë'o}     # push a space if we're on the 2nd iteration, else push "o"
ð            # push a space
NÉis}        # if we're on an odd numbered iteration, swap the stacks top 2 chars
"|-|  "      # push this string
J            # join the stack to one string
N1›iR}       # if we're on the any of the last 3 iterations, reverse the string
,            # print row

Generate bottom row

…──|  # push the string "──|"
     # push a reversed copy
'-s   # push "-" between the 2 strings on the stack
ðð    # push 2 spaces
X     # push the N we saved in the main loop (current sheep number)
J,    # join and print row
share|improve this answer

QBasic, 110 bytes

INPUT n
FOR i=0TO 5*n-1
CLS
?
?"  |-|"
?"--|-|-- ";i\5
x=i MOD 5
LOCATE(x=2)+2,1+x-(x>1)+x\3
?"o"
SLEEP 1
NEXT

Loops over 5*n ticks. At each tick, clears the screen, prints the stile and sheep count, and then uses LOCATE to print the o at the appropriate spot. With x being the position code between 0 and 4:

  • Row: (x=2)+2
    • If x=2 is true, -1+2 = 1
    • If x=2 is false, 0+2 = 2
  • Column: 1+x-(x>1)+x\3
    • If x is 0 or 1, x>1 is false and x\3 is 0: 1+x-0+0 = 1 or 2
    • If x is 2, x>1 is true and x\3 is 0: 1+x-(-1)+0 = 4
    • If x is 3 or 4, x>1 is true and x\3 is 1: 1+x-(-1)+1 = 6 or 7

Finally, SLEEP for 1 second and loop. If you don't mind hitting enter at every frame, I can shave two bytes by removing the argument to SLEEP.

share|improve this answer

PHP+JavaScript, 168 bytes

<?extract($_GET);$s="     ";$s[$f=++$f%5]=o;echo strtr("<pre>   C
AB|─|DE
──|─|── $c",EABCD,$s),($c+=!$f)<$n?"<script>location.href='s.php?n=$n&c=$c&f=$f'</script>":"";

Save to file s.php, call in browser with s.php?n=<n>.

Calls itself with new parameters for every frame, no delay.


I could save 5 more with index.php; but I don´t want to go that far.

share|improve this answer
    
I've tried running this on PHP 5 and 7, but all Chrome gives me is C AB|─|DE ──|─|── $c",EABCD,$s),($c+=!$f)<$n?". – steenbergh yesterday
    
@steenbergh You have short_open_tag disabled. Enable it (default) or add php+space after <?. – Titus 19 hours ago
    
Yup, that's it. Got it running now. – steenbergh 19 hours ago

Jelly, 55 54 53 bytes

ị30214D¤“o    ”ṙ“   “
““|-|““
__|-|__  ”ż
×5Ḷµ:5ż@Ç€Y

TryItOnline

Prints frames separated by line feeds.

How?

ị30214D¤“o    ”ṙ“   “
““|-|““
__|-|__  ”ż           - Link 1, build a frame without counts: frameNumber
       ¤              - nilad and link(s) as a nilad:
 30214                -     literal 30214 (a nilad)
      D               -     to decimal: [3,0,2,1,4]
ị                     - index into (1-based and modular, so frames go 4,3,0,2,1,4,...)
        “o    ”       - string "o    "
               ṙ      - rotated to the left by that number
                “   “ - the rest, except the last character, is:
““|-|““               -     an array of strings ["   ","\n","","|-|","","\n__|-|__  "]
__|-|__  ”            -     i.e. split where a sheep might go

          ż           - zip the sheep (the rotated "o    ") into that

×5Ḷµ:5ż@Ç€Y - Main link: nSheep
×5          - multiply by 5 -> nFrames
  Ḷ         - lowered range: [0,1,2,...nFrames-1]
   µ        - monadic chain separation
    :5      - integer division by 5 (vectorises): [5 zeros, 5 ones, ..., 5 (nSheep-1)s]
      ż@    - zip with reversed arguments
        ǀ  - call last link (1) as a monad for each (zip sheep numbers with frames)
          Y - join with line feeds (TODO: replace with future animate frames atom :p)
share|improve this answer

node.js, 146 142 bytes

Tested with ubuntu terminal only:

i=0;setInterval(function(){console.log('\033[2J'+'   2\n01|-|34\n──|-|──  '.replace(i%5,'o').replace(/\d/g,' ')+Math.floor(i++/5))},9)

Well, that's a frame every 9 ms. A more sleep-soothing version (frame every 1s):

i=0;setInterval(function(){console.log('\033[2J'+'   2\n01|-|34\n──|-|──  '.replace(i%5,'o').replace(/\d/g,' ')+Math.floor(i++/5))},1000)

And ungolfed:

var i = 0;
setInterval(function(){
  console.log('\033[2J' + '   2\n01|-|34\n──|-|──  '.replace(i%5, 'o').replace(/\d/g, ' ') + Math.floor(i++/5));
}, 1000)
share|improve this answer

PHP, 132 bytes

<?php $i=0;for(;;){system("clear");$c="  \n  |-|  \n──|-|──  ";$c[[3,4,1,8,9][$i%5]]='o';echo"  $c".floor($i++/5);sleep(1);}

Tested on ubuntu (don't know, if system("clear") works on windows)

Ungolfed:

<?php
$i = 0;
for(;;) {
  system("clear");
  $content = "  \n  |-|  \n──|-|──  ";
  $content[[3,4,1,8,9][$i%5]] = 'o';
  echo "  $content " . floor($i++/5);
  sleep(1);
}
share|improve this answer
    
Idk either about Windows, but I´m sure that clear needs no quotes. – Titus 13 hours ago
    
Thinking about Windows ... it was cls in DOS. – Titus 12 hours ago
    
Remove the $i=0;, warnings are typically not displayed in code golf (-5 bytes). For the same reason, you don't need quotes around clear and o (-4 bytes). Replace the \ns by real newlines (-2 bytes). Since you only have expressions, not any statements, you can put everything but the last one in your for loop, allowing you to remove the brackets (for(;;system(clear),$c=…)sleep(1);) (-2 bytes). And finally, you forget to add the condition $i<$argv[0] (+ 11 bytes). – Blackhole 11 hours ago

Python 2, 171 159 144 bytes, 163 151 136 characters

Solution using a recursive function. Call as f(int)

EDIT

-12 after rereading the comments and seeing that the count does not have to increment when the sheep reaches the end of the field

-15 by iterating through the index list directly and losing a variable

def f(a,x=0):
 if a>0:
  for c in 5,6,3,10,11:
   b=list('    \n  |-|  \n──|-|──  ');b[c]='o';print"\n"*50+"".join(b)+(`x`)
  f(a-1,x+1)

Notes

Assumes UTF-8 encoding

Using - instead of ─ (as in @Luis MATL answer) would bring the byte count down by 8 to match the character count and would lose the UTF-8 dependency

50 newlines added - output is at the bottom on the console (cheaper than importing and using os.system("clear") and works on Windows and Linux)

Version with 1 second time delay between outputs (170 bytes, 162 characters)

import time
def f(a,x=0):
 if a>0:
  for c in 5,6,3,10,11:
   b=list('    \n  |-|  \n──|-|──  ');b[c]='o';print"\n"*50+"".join(b)+(`x`);time.sleep(1)
  f(a-1,x+1)
share|improve this answer

Bash + standard Linux utilities (339 bytes)

e(){ echo "$@";}
n(){ e -n "$@";}
r(){ [ $? -eq 0 ]&&s=o||s=" ";[[ $1 ]]&&n " $s "||n "$s";}
f(){ k=$(($1%5));n "  ";[ $k -eq 2 ];r .;e "  ";for i in 0 1;do [[ $k -eq $i ]];r;done;n "|-|";for i in 3 4;do [[ $k -eq $i ]];r;done;e;n "──|-|──";}
for l in `seq 1 $1`;do for z in `seq 0 4`;do clear;f $z;e "  $((l-1))";sleep 1;done;done
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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