Why a Simulator?

Kids these days don't have the time nor the ambition to actually go and stack boxes on the see-saw or play around with balancing physical objects. This leaves lots of room in the software market for a Lever Simulator which will, according to my models, sell like mad!

Programming Help Wanted

I've filed the patent for such a game (pending), but need an expert programmer to write the game-logic for me. From my understanding, it is standard practice to compensate programmers based on the size in bytes of the final program. As such I will be awarding this lucrative contract to the lowest bidder.


A lever is a series of boxes or empty spaces that is balanced by a fulcrum. Each box has a particular weight one through nine and spaces have no weight. As you know, a box's weight on the lever is directly proportional to how far that box is from the fulcrum. A box of weight 4 that is on the third space from the fulcrum will contribute 12 effective units of force to that side of the lever.

I need a program that, given an input lever, will output whether the lever will skew toward the left, the right, or be perfectly balanced.

I/O Guidelines

  • You will write for me a program.
  • The input will contain one line of text.
  • The input will come from stdin or as one command-line string.
  • Boxes will represented by the characters '1' through '9'. These characters represent their respective weights. An empty space will be represented by a space ' '. The fulcrum will be represented by a caret '^'.

A sample input lever could look like: 8 2^ 941

This lever is perfectly balanced: (4*8) + 0 + 0 + (1*2) == 0 + (2*9) + (3*4) + (4*1) == 34

  • There will be no leading nor trailing spaces. There will be no trailing newline.
  • No need to handle malformed input, input will always have exactly one fulcrum, and only numbers and spaces.
  • The output will indicate whether the lever is left-heavy, right-heavy, or balanced.
  • Your program must have exactly 3 possible outputs that could result from a well-formed input. You can choose what these are.
  • The output must either be print to stdout or be the return code of the program.

Test cases

Here I use L,R,B to mean left-heavy, right-heavy, balanced:

  1. Input: 11 ^9 Output: B

  2. Input: 321^ 12 Output: L

  3. Input: 9^ 1 Output: R

(If anyone has some "trickier" test cases, feel free to edit them in).


Not-necessarily-inspired-by, but related to Balance a set of weights on a seesaw

  • 8
    \$\begingroup\$ The output must either be print to stdout or be the return code of the program. Well, now you're asking me to make a distribution of Linux which uses seesaw-notation for exit codes. \$\endgroup\$
    – cat
    Commented Nov 24, 2015 at 22:42
  • 1
    \$\begingroup\$ I'd go play on the see-saw / teeter-totter, except most playgrounds have removed them since they are "unsafe". I hope they never remove swings for that reason. "Kids might jump off of them, oh no!" \$\endgroup\$
    – mbomb007
    Commented Nov 24, 2015 at 22:50
  • 2
    \$\begingroup\$ Can input have empty sides? As in ^16, 16^ or ^? (Assume it can) \$\endgroup\$
    – Runium
    Commented Nov 25, 2015 at 0:17
  • \$\begingroup\$ ahhh a hole in the spec, yeah I'd assume sides can be empty \$\endgroup\$ Commented Nov 25, 2015 at 1:11
  • 7
    \$\begingroup\$ I just spent several long seconds wondering how 11 offset by 3 or 4 can possibly be balanced with 9 offset 1. \$\endgroup\$ Commented Nov 25, 2015 at 12:41

19 Answers 19


Javascript ES6, 62 Bytes

  • -1 if left is heavier
  • 0 if balanced
  • 1 if right is heavier


  Math.sign(                     // output sign of weight of lever
    [...s].reduce((p,c,i)=>      // split and reduce input
      p+~~c*(i-s.indexOf`^`),0)) // add weights of all elements
                                 //   (elements left of pivot are negatively weighted)

Test runs (assigning anonymous function to f):

>> f("11   ^9")
<< 0

>> f("321^  12")
<< -1

>> f("9^         1")
<< 1

  • -11 bytes: changed output from R B L to -1 0 1
  • -3 bytes: changed e.split`` to [...e] (thanks @Vɪʜᴀɴ)
  • -33 bytes: changed algorithm to use negative weights rather than splitting at pivot
  • -9 bytes: removed pivot check (apparently, ~~'^' evaluates to 0...)
  • -2 bytes: made function anonymous (thanks @cᴏɴᴏʀ-obʀɪᴇɴ)
  • 3
    \$\begingroup\$ It is general consensus that you can omit the leading f= and say that it generates an anonymous function. (-2 bytes FYI) \$\endgroup\$ Commented Nov 25, 2015 at 2:44

Python 2, 69 bytes

lambda s:cmp(sum(ord(c)%16*(i-s.find('^'))for i,c in enumerate(s)),0)

The modulus ord(c)%16 extracts the value of a digit character while getting 0 for space. For each character, its torque contribution is computed as its weight times the signed distance to the pivot i-s.find('^'), and these are summed and compared to 0, producing one of -1,0,1. The character ^ is computed to have weight 14, but that doesn't matter because it's on the pivot.

An 18-byte Pyth port by Maltysen:


For the Python code, if a full program is required, here's 79 bytes. The idea is to start the index i shifted by s.find('^'), and have it count down.

for c in s:t-=ord(c)%16*i;i-=1
print cmp(t,0)
  • \$\begingroup\$ Here is a Pyth program using your method which you can post if you want pyth.herokuapp.com/… 18 bytes. Didn't feel right about posting it myself. \$\endgroup\$
    – Maltysen
    Commented Nov 25, 2015 at 0:54
  • \$\begingroup\$ @Maltysen Thanks, I included it. \$\endgroup\$
    – xnor
    Commented Nov 25, 2015 at 1:33

Japt, 22 bytes

Japt is a shortened version of JavaScript. Interpreter

U¬r@X+~~Y*(Z-Ub'^),0 g

Returns -1 for L, 0 for B, and 1 for R.

How it works

Uq r@X+~~Y*(Z-Ub'^),0 g
                         // Implicit: U = input string
Uq r@              ,0    // Reduce the input by this function, starting at 0:
     X+~~Y*              //  Return the previous value, plus the current value times
           (Z-Ub'^)      //   the current index minus the index of "^" in U.
                      g  // Take the sign of the resulting number.
                         // Implicit: output last expression

APL, 39 30 bytes


After rereading the rules, I've changed this to output -1 0 1 instead of L B R, saving nine bytes.

Try it here.


Pyth, 20 bytes


Test suite

-1 for left-biased, 0 for balanced, 1 for right-biased.

How it works:

                        z = input()
             m     z    Map over z
              .x        try:
                sd           cast charater to int
                  0     except: 0
                        Lever arm:
           Uz           range(len(input()))
     -Rxz\^             Subtract index of caret from each value.
   *V                   Vectorized multiplication.
  s                     Sum.
._                      Take sign and print.

Haskell, 116 96 82 76 bytes

 f x=signum$sum$zipWith(*)[-length(fst$span(<'^')x)..]$(`mod`16).fromEnum<$>x

Output is 0 for balanced, -1 for left-heavy and 1 for right-heavy.

Usage example: f "321^ 12" -> -1

How it works: find the part before the ^. Multiply the input string and the list of weights which starts at - length-of-first-part. The ^ has a weight of 0 and doesn't add to the sum. I'm using @xnor's mod 16 trick to convert digits/spaces to integer values. If the sum is negative (positive), the lever is left-heavy (right-heavy) and balanced if the sum is 0.


TeaScript, 23 bytes 25

I tried writing a Pyth answer but that went horribly :\


That ² looks so out of place but it saves 1 byte, so I'll be keeping it.

Try it online!

Test all cases

For the output scheme I've chosen:

  • -1 if Left is heavier than Right (L)
  • 0 if Left is as heavy as Right (B)
  • 1 is Left is less heavy than Right (R)

Ungolfed && Explanation

This uses maps and reduces to get the job done.


              // Implicit: x = input
$C(           // Compare...
  xd(#        // Reduce...
    l+          // Pending weight...
    ~~i         // Current weight -> int times...
    (a-         // Total length minus...
    xi`^`       // Fulcrum location
)             // Implicit: Output result

pb, 349 329 bytes


This was a tricky one. pb was not designed to be good at this kind of thing. It doesn't even have multiplication. But hey, it works.

Ed. note: Did I just say pb has no multiplication? What? pb definitely definitely has multiplication. I designed and implemented this language, I should know that it has multiplication built in and I don't have to do some silly looped addition. Fixing that (as well as doing some creative rearranging now that I could approach that part of the problem from [almost literally] a different angle) saves me 20 bytes. Embarrassing.

The hardest part was, after getting the sums of (weight*distance) for each side, actually determining which letter to print. pb doesn't have > or < operators, just == and !=. There's no easy way to tell which value is larger. I can't even subtract and compare with 0... unless I do something really silly.

  • Find the sum of the two sums.
  • Go that far to the right, on a line that's not being used for anything.
  • Until reaching X=0, go left and place 'L's.
  • Place a 'B' at X=0.
  • Go left by the sum of the two sums.
  • Until reaching X=0, go right and place 'R's.

Then, you simply go to X=(left side - right side), and there's your answer! Delete everything on that line to clean up, and then print the value that was found at (0, 0).

...But there's a slightly shorter way. Instead of using 'L', 'B' and 'R', use those values - 'B' and add 'B' back on when printing. That way, you don't ever have to place 'B' at X=0, you just leave it as the 0 it already was. The only problem is that once you do this, the program becomes very goofy in watch mode. 'L'-'B'==76-66==10=='\n'. Everything seems to be working fine, until suddenly a huge number of newlines are printed and it's impossible to keep track of what's going on :D In pbi's regular execution mode, though, everything works fine because the newlines are deleted before anything is printed to the console.

^w[B!94]{>}                 # Find the fulcrum

w[B!0]{                     # Starting at the fulcrum and going right:
    vb[T]^                    # Store the T below each character of input
    t[T+1]                    # Increment T

vb[46]                      # Put a '.' at the end of the values below the input

<w[B!0]{<}                  # Go to the space below the fulcrum
b[1]                        # Put a 1 (So the fulcrum will be represented as '.' later)
vvb[46]^^                   # Put a 46 two spaces below it

t[X]                        # Store the current X value in T
w[X!0]{<                    # Until reaching the beginning of the input:
    b[T-X]                    # Put T - (the current X value) below each byte

^w[B!0]{                    # For each byte of input:
    w[B=32]{b[48]}            # Set spaces to '0'

w[X!0]{<                    # For each byte of input:
    t[B-48]                   # Set T to the value of the number (fulcrum becomes '.')
    vb[B*T]^                  # Multiply the value below by T

# This has nothing to do with the input, except that it's the right length:
w[B!0]{                     # For every byte of input:
    v                         # Go to the value below it
    t[B]                      # Store it in T
    vb[1]>^                   # Put a flag below it
    w[B!46]{>}                # Go to the next '.' value
    vvb[B+T]                  # Add T to whatever is two spaces below the '.'
                              # This will cause the sum for the right side of
                              # the fulcrum to be 46 too high. This is why 46
                              # was left below the fulcrum earlier: both sums
                              # will be off by the same amount.
    ^w[B=0]{<}                # Go back to the flag
    b[0]^b[0]                 # Erase the flag and the value above it

vb[0]                       # Erase the stray '.'
vvt[B]<w[B!0]{<}t[B+T]      # Get the sum of the two sums
^>[T]                       # Go right that far
w[X!0]{b[10]<}              # Head back to X=0, leaving 'L'-'B' the whole way
<[T]                        # Go left the same amount as before
w[X!0]{b[16]>}              # Head back to X=0, leaving 'R'-'B' the whole way
vw[B=0]{>}                  # Find the sum from left of the fulcrum
t[B]b[0]                    # Save it to T and erase it from the canvas
w[B=0]{>}                   # Find the other sum
t[T-B]b[0]                  # Subtract it from T and erase it from the canvas
^<[X-T]                     # On the line that was just prepared, go to X=T
t[B]                        # Save the value of that space to T
<[X]>w[B!0]{b[0]>}          # Erase the entire visible part of that line
<[X]^b[T+66]                # Print (the value read from that line)+'B' at (0, 0)
  • 3
    \$\begingroup\$ Like watching the descent of a man into madness. \$\endgroup\$
    – Kzqai
    Commented Dec 1, 2015 at 23:15

𝔼𝕊𝕄𝕚𝕟, 22 chars / 38 bytes


Try it here (Firefox only).

  • 2
    \$\begingroup\$ -1 this is optimizing for char count, not byte count \$\endgroup\$
    – user45941
    Commented Nov 25, 2015 at 5:11
  • \$\begingroup\$ That's what 𝔼𝕊𝕄𝕚𝕟 was built for, @Mego. \$\endgroup\$ Commented Nov 25, 2015 at 5:14
  • 3
    \$\begingroup\$ Regardless of what it was built for, the scoring is in bytes. \$\endgroup\$
    – user45941
    Commented Nov 25, 2015 at 5:15
  • \$\begingroup\$ I understand that. \$\endgroup\$ Commented Nov 25, 2015 at 5:17

Perl 5, 72 bytes


MATLAB 91, 57, 55 Octave, 50 bytes

I did not expect to golf this further, but switching to Octave made it possible to save 5 additional bytes! Wow, this one took time...


It outputs -Inf, NaN, Inf for L, B, R respectively.

Test suite!


This is definitely a hard-to-read code, but I'll try to explain as well as I can. I will switch between code block explanation and text.

@(x)                 % Anonymous function that takes a string x as input
           +x        % Convert the string into a numeric array, 
                     % where each character is represented by its ASCII-value
       mod(+x,16)    % Takes this string modulus 16, to make spaces (ASCII 32) equal 0 
    (s=mod(+x,16))   % Assigns this numeric array to s, thanks to Octave's awesome 
                     % inline variable assignment possibility
    (s=mod(+x,16))*  % Multiply s by the vector inside the brackets    

Let's look at what's going on inside the brackets:

      find(s>9)             % The only value in the vector s that's larger than 9, 
                            % after the modulus is ^, (it's now 14)             
   (i=find(s>9))            % Assign the position of `^` to the index variable i

This one is a bit tricky:


The numbers on each side of the ladder must be multiplied by the distance from the caret. If we use negative numbers on the left side, and positive numbers on the right side we can simply sum the vector to see which side is heaviest.

Suppose the input string is: '321^ 12'. We want the following: 3*(-3)+2*(-2)+1*(-1)+1*3+2*4. The vector we made inside the brackets starts at 1-i, which in this case is -3, since the caret is in the 4th position. It goes up to nnz(x)-i in increments of one. We can use nnz(x) instead of numel(s), because x is a string containing no zeros.


ans =
  -3  -2  -1   0   1   2   3   4

Now, we could do element-wise multiplication s.*[...], and take the sum of this. But, since we have two vectors, we can also mutliply s by the transposed of [...] and calculate the sum using matrix multiplication:


This gives us either a negative number, meaning the left side is heavier, a zero, meaning it's balanced, or a postive numbers, meaning the right side is heavier. Instead of using the naive approach of sign(...), we multiply it by inf, which will give us either -Inf or Inf for left and right respectively. We get NaN for 0*inf, since it's undefined.

This gives us three distinct values for the three possible outcomes.


JavaScript, 146 bytes


Pretty massive.


  • \$\begingroup\$ You could save quite a few bytes using ES6. The whole function t(s){ could become t=>{ and split('^') could become split`^` \$\endgroup\$
    – Downgoat
    Commented Nov 24, 2015 at 23:51
  • \$\begingroup\$ @Vɪʜᴀɴ you did probably mean s=>{? \$\endgroup\$
    – nicael
    Commented Nov 25, 2015 at 0:05
  • \$\begingroup\$ oh yes, sorry, that's what I meant \$\endgroup\$
    – Downgoat
    Commented Nov 25, 2015 at 0:06
  • \$\begingroup\$ @Ypnypn -6 chars :) \$\endgroup\$
    – nicael
    Commented Nov 25, 2015 at 18:11

Ruby, 111 108 bytes

->s{l,r=s.split'^';v=->x{x.chars.map.with_index{|c,i|c.to_i*(i+1)}.reduce:+};%w(B L R)[v[l.reverse]<=>v[r]]}


Sums up weighted value of each number on each side. Then it uses the ruby spaceship operator to provide a 1,0,-1 of equality/inequality of the two sides, which is the index of an array with the correct output.


PowerShell, 83 73 Bytes


Thanks to TessellatingHeckler for the golf.

Uses essentially the same algorithm as the below older code, but here we iterate through the characters in the input string one at a time rather than iterating through the index, which saves a handful of bytes. Still throws the same spectacular error message when the algorithm reaches ^ - doesn't affect STDOUT.



Uses the same awesome algorithm as Dendrobium's excellent answer, and thus uses the same output of -1 / 0 / 1 if the input is left-heavy / balanced / right-heavy.

Ugh. Long because of a casting quirk feature that PowerShell has. Most pertinent here is how char multiplied by int functions. Taking an array-index of a string results in a char object. PowerShell converts the char to its corresponding ASCII value (rather than literal value) before multiplication. So, something like $a='012'[0];[int]$a*2 results in 96.

That means we need to re-cast it back as a string. However, simply doing string times int gives us a string repeated that many times. For example, $a='0';$a*2 would result in 00.

This means we need to cast the char back as a string before re-casting as int, then multiplication can happen, before we add it into our accumulator $x.

Couple that with the lengthy way to iterate through a string, and the .NET call to output the sign, and we get a pretty long piece of code.

NB - This will throw a spectacular error when it reaches ^ in the string, stating that it can't convert it to an int. Doesn't affect STDOUT.

  • \$\begingroup\$ I have param($b)$i=-$b.indexOf('^');[char[]]$b|%{$x+=$i++*+"$_"};[math]::Sign($x) at 74 bytes. This took a long while and several approach attempts. math::sign looks so long, but I can't see any way to improve that bit. \$\endgroup\$ Commented Dec 17, 2015 at 7:31
  • \$\begingroup\$ @TessellatingHeckler Sure, iterating through the characters themselves rather than the indices ... makes sense! I golfed an additional byte by using PowerShell's implicit casting $i++*+"$_" is equivalent to $i++*"$_" if $i is an int. \$\endgroup\$ Commented Dec 17, 2015 at 13:47

CJam, 29 bytes

l_'^#\"^ "'0er'0f-_,,@fm.*:+g

Try it online

Result is -1 for left-heavy, 0 for balanced, 1 for right-heavy.

This seemed a bit lengthy, but I tried a bunch of alternatives, and they all ended up between 29 and 33 bytes. One problem is that I couldn't find a way of converting the string to values that would automatically result in 0 for the spaces. So I ended up explicitly replacing the spaces with '0 characters, which obviously adds to the length of the code.

Alternatives tried:

  • Splitting string at '^, reversing the 1st one, and then calculating the weighted value for both.
  • Using the ee operator to add the index to the list of values.
  • Instead of subtracting the caret position from each index, calculate the dot product without the subtraction, and then subtract caret position times string length from the result.


l         Get input.
_'^#      Copy and find caret position.
\         Swap input back to top.
"^ "'0er  Replace caret and spaces with '0.
'0f-      Subtract '0 from all characters, to get integer values.
_,,       Build index array with same length.
@         Rotate caret position to top.
fm        Subtract it from all indices.
.*        Calculate element wise product of two vectors.
:+        Add up the element products to get dot product.
g         Signum.

Python 3, 196 114 bytes

for E in I:
 if E.isdigit():r+=int(E)*(p-i)

Regular code:

total = 0


for num in inp:
    if num.isdigit(): total += int(num) * (ful_index - i)



  1. Generates a list of numbers + the fulcrum from stdin.
  2. For every number, adds the distance from the fulcrum times the number to the variable to the total (numbers on the left will be negative and numbers on the right will be positive).
  3. Prints the correct letter depending on the result (B if equal, L if more than zero, and R if less than zero).

Huge thanks to @ThomasKwa for trimming 82 bytes (more than 40%) off!

  • \$\begingroup\$ An easy 15 or so bytes: Use print('LBR'[(B>D)-(B<D)]) for the end, and B=D=0 at the start. \$\endgroup\$
    – lirtosiast
    Commented Nov 24, 2015 at 23:50
  • \$\begingroup\$ No, even better: don't keep track of the left and right separately; instead multiply by a negative distance for numbers left of the ^. That saves you the abs() too. \$\endgroup\$
    – lirtosiast
    Commented Nov 24, 2015 at 23:53

C, 140 139 138 134 100 bytes


  • 1 = LEFT
  • 2 = BALANCED
  • 0 = RIGHT
k;main(int x,char**a){char*n=a[1],*g=n;for(;*n^94;++n);for(;*g;++g)k+=(*g&15)*(n-g);return!k?2:k>0;}


./see-saw "11   ^9"
echo $?

As we have ASCII:

SPACE = 0x20
    0 = 0x30 ... 9 = 0x39

We get:

0x20 & 0x0f = 0
0x30 & 0x0f = 0
0x31 & 0x0f = 1
0x32 & 0x0f = 2
... etc.

Then sum by factor distance to ^.


SpecBAS - 140 bytes

1 INPUT b$: LET t=0,p=POS("^",b$),l$="RBL"
2 FOR i=1 TO LEN b$
3 IF b$(i) IN ["1" TO "9"] THEN INC t,(p-i)*VAL b$(i)
4 NEXT i
5 TEXT l$(2+SGN t)

t is a running total, the values are negative when character position is more than the carat position. At the end it sees if total is negative, zero or positive and prints the corresponding character of R, B or L.

I could shave a few bytes off by just outputting -1, 0 or 1 like some of the other answers.


Java, 83 bytes

l->{int s=0,l=0;for(char c:l)if(l<1)s-=c-48;else s+=c-48;return s<0?-1:(s>0?1:0));}

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.