32
\$\begingroup\$

Balancing Act

Overview

Given an input of 3 single-digit positive integers representing a set of weights, output an ASCII representation of a seesaw with the weights placed on it so that it is in balance around a central pivot, taking lever effects into account.

Each number has a weight equal to its value. The torque of each number is the weight multiplied its the distance from the center in characters. For the seesaw to be in balance, the sum torque of the weights on the left of the seesaw must equal that of those on the right, like this.

Input

3 integers in the range of 1-9. You can input the integers however is convenient, e.g. a tuple, 3 comma-separated values etc. However your program must be able to handle numbers input in any order (i.e. no assuming the values will be sorted). Duplicate numbers may be input (e.g. 2,3,2).

The inputs will always mathematically allow for a valid output, otherwise the input is not valid.

Output

The output should be a 2-line ASCII representation of the seesaw with the weights placed on it. On the first line are the digits, spaced in order to balance them on the seesaw.

Numbers may not be placed in the very center of the scale, where the distance and therefore the torque would be zero. Valid distances from the center range from 1-10 characters inclusive to the left or right of the pivot.

In the spaces unoccupied by the numbers are 18 underscore characters (a center underscore and 10 on each side, minus the 3 positions occupied by the numbers). On the last line is a single caret character aligned with the center of the scale, representing the pivot.

Examples

Input:

4,7,2

Output:

________7___42_______
          ^

7*2 = 4*2 + 2*3

Numbers can be output on either side, for example this would also be valid:

_______24___7________
          ^

2*3 + 4*2 = 7*2

Numbers can be placed anywhere on the scale as long as they balance, e.g:

Input:

3,1,5

Output:

_____5________1__3___
          ^

5*5 = 1*4 + 3*7

or

____5________1_____3_
          ^

5*6 = 1*3 + 3*9

or

____5___________1_3__
          ^

5*6 = 1*6 + 3*8

etc

Your program only has to output one of the valid outputs. It does not have to output an error if the input is not valid.

Notes

  • This is so the shortest program in bytes wins
  • Program may be a stand-alone or a function that accepts the numbers as input and returns a string.
  • Trailing newline and white-space on last line is optional
  • If you don't know what a seesaw is, it's also known as a teeter-totter or a teeterboard.
\$\endgroup\$
3
  • \$\begingroup\$ Here's a paste showing valid inputs and solutions (with some duplication) \$\endgroup\$
    – samgak
    Commented Aug 6, 2015 at 7:36
  • 12
    \$\begingroup\$ An excellent first challenge! An interesting problem and a thorough spec. \$\endgroup\$
    – xnor
    Commented Aug 6, 2015 at 7:58
  • 2
    \$\begingroup\$ Algorithmically, given a whole-numbered vector, this asks you to find a whole-numbered orthogonal vector with all different entries. \$\endgroup\$ Commented Aug 7, 2015 at 1:34

9 Answers 9

13
\$\begingroup\$

CJam, 40 39 38 bytes

q~21Ue]e!{21,Af-Aest.*:+!}=0'_erNAS*'^

Try it online.

How it works

q~                                     e# Read and evaluate the input.
  21Ue]                                e# Append zeroes to achieve a length of 21.
       e!                              e# Push all unique permutations.
         {               }=            e# Find the first permutation such that:
          21,                          e#  Push [0 ... 20].
             Af-                       e#  Subtract 10 from each.
                Aest                   e#  Replace the element at index 10 with the
                                       e#  current time (ms since epoch) to push
                                       e#  [-10 ... -1 <big number> 1 ... 10].
                    .*                 e#  Multiply each number of the permutation
                                       e#  by the corresponding distance.
                      :+               e#  Add the products.
                                       e#  The timestamp makes sure that this sum
                                       e#  is non-zero for a non-zero element in
                                       e#  the middle of the permutation.    
                        !              e#  Push the logical NOT of the sum.
                           0'_er       e# Replace zeroes with underscores.
                                NAS*'^ e# Push a linefeed, ten spaces and a caret.
\$\endgroup\$
5
\$\begingroup\$

CJam, 46 44 bytes

'_21*q~K,Am3m*{___&=*Afm1$.*:+!}=.{\t}NAS*'^

Test it here.

Explanation

First, an observation: we never need to put two digits on the ends of the seesaw. Whenever that's a valid solution, there is at least one other valid solution (according to the pastebin in the comment on the challenge).

'_21*   e# Push a string of 21 underscores.
q~      e# Read and eval input.
K,      e# Push the array [0 1 .. 19 20]
Am      e# Remove the 10. This is now an array of all valid positions on the seesaw.
3m*     e# Get all 3-tuples of valid positions.
{       e# Select the first tuple for which the following block yields a truthy result.
  ___   e# Make three copies of the tuple.
  &=    e# Intersect the last two copies and check for equality with the first one.
        e# This yields 1 if all positions are distinct, and 0 otherwise.
  *     e# Repeat the original tuple that many times. That is, if the positions are
        e# distinct, leave the tuple unchanged. Otherwise, replace it with an empty array.
  Afm   e# Subtract 10 from each position to get its weight.
  1$    e# Copy the input digits.
  .*    e# Take the pairwise product of weights and digits. If the weights are empty
        e# (because they were not unique), this will just yield a list of the digits.
  :+    e# Sum the weighted digits. If the weights were not unique, this will just sum
        e# the digits and will always be positive.
  !     e# Logical NOT - give 1 if the sum was 0, or 0 otherwise.
}=
.{\t}   e# For each pair of digit and position, replace that position in the underscore
        e# string with the corresponding digit.
N       e# Push a newline.
AS*     e# Push ten spaces.
'^      e# Push a caret.
\$\endgroup\$
5
\$\begingroup\$

Java, 519 414 321 bytes

static int f(int a,int b,int c){int i,j,k;for(i=-10;i<=10;i++)for(j=i+1;j<=10;j++)for(k=j+1;k<=10;k++){if(a*i+b*j+c*k==0&&i!=0&&j!=0&&k!=0){for(int q=0;q<21;q++){if(q==10+i)p(a);else if(q==10+j)p(b);else if(q==10+k)p(c);else p('_');}p("\n          ^\n");return 0;}}return 0;}static void p(Object a){System.out.print(a);}}

My first attempt at golfing.

You can call it with f(a,b,c). Try it here

EDIT: Used izlin method of check (a*i+b*j+c*k)==0

EDIT: Thanks, J Atkin for the golfing suggestions.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ You can save a few bytes by changing the signature of p to Object a and using it in place of the other 2 System.out.print(ln) s. \$\endgroup\$
    – J Atkin
    Commented Aug 6, 2015 at 23:48
  • 1
    \$\begingroup\$ And since a is used only once, you could inline it. \$\endgroup\$
    – J Atkin
    Commented Aug 6, 2015 at 23:51
5
\$\begingroup\$

Pyth, 67 58 53 49 bytes

This feels a little on the huge side for Pyth, but I'm not nearly familiar enough with the language to be able to get this much smaller. Sub 50 bytes, I'm finally happy with this!

V.c-KrT-011Z3FY.pQIqs*VNYZjkm?}dN@YxNd\_K+*dT\^.q

Input is expected as an array of integers, for example [1,2,3]. Try it here.

Explaination:

V.c-KrT-011Z3FY.pQIqs*VNYZjkm?}dN@YxNd\_K+*dT\^.q
                                                       Implicit: Q = eval(input())
     rT-011                                            Create range from 10 to -10
    K                                                  Store in K
   -       Z                                           Drop 0 from the above
V.c         3                                          For N in (combinations of the above of size 3)
             FY.pQ                                     For Y in (permutations of input)
                     *VNY                              Multiply each element in N by the corresponding element in Y
                    s                                  Take the sum
                  Iq     Z                             If it's equal to zero:
                            m           K              For d in K (K = [10, ..., -10])
                             ?}dN                      Is d in N?
                                 @YxNd                 If so, get corresponding value from Y
                                      \_               Otherwise, get '_'
                          jk                           Join the resulting array into a string (implicit print)
                                         +*dT\^        Join 10 spaces and '^', implicit print
                                               .q      Break all loops and exit

And finally, some example inputs and outputs:

[1,1,1] ->
1__________1_______1_
          ^

[2,9,5] ->
2____5_________9_____
          ^

[9,8,5] ->
5____8______________9
          ^
\$\endgroup\$
4
\$\begingroup\$

C - 237 228 Bytes

i,j,k;f(a,b,c){char o[]="_____________________\n          ^";for(i=-10;i<9;i+=i+1?1:2){for(j=i+1;j<11;j+=j+1?1:2){for(k=j+1;k<11;k+=k+1?1:2){if((a*i+b*j+c*k)==0){o[i+10]=a+48;o[j+10]=b+48;o[k+10]=c+48;printf("%s",o);return;}}}}}

You can call it with f(a,b,c).

Try it here.

Example outputs:

f(4,7,2):
4_____________7_2____
          ^         

f(3,1,5)
3____1___________5___
          ^       
\$\endgroup\$
1
3
\$\begingroup\$

Python 2.7 235 226 219 Bytes

def s(n,p=__import__("itertools").permutations):
 l=["_"]*21
 for p,q in[[(a,x+10),(b,y+10),(c,10-z)]for a,b,c in p(n,3)for x,y,z in p(range(1,11),3)if x!=y and a*x+b*y==c*z][0]:l[q]=`p`
 return`l`[2::5]+"\n"+" "*10+"^"

Testing it with some basic examples- (1,1,1),(1,2,1),(3,1,5),(4,7,2) results in- :

(1, 1, 1)
_______1___11________
          ^
(1, 2, 1)
_____1_____12________
          ^
(3, 1, 5)
________5__3_____1___
          ^
(4, 7, 2)
_2_________47________
          ^

Outputs for all possible inputs pasted here

\$\endgroup\$
4
  • \$\begingroup\$ "".join(l) -> 'l'[2::5] is one byte shorter (replace the quotes with backticks). \$\endgroup\$
    – Kade
    Commented Aug 6, 2015 at 13:25
  • \$\begingroup\$ Also, if you're willing to change your approach from a function to a program, you can golf this down to 222 bytes. \$\endgroup\$
    – Kade
    Commented Aug 6, 2015 at 13:31
  • \$\begingroup\$ @samgak oops. My bad, thought I read the question properly. 2 more bytes :( \$\endgroup\$
    – Kamehameha
    Commented Aug 6, 2015 at 16:42
  • \$\begingroup\$ @Vioz- Awesome tip. Didn't know about repr. :) \$\endgroup\$
    – Kamehameha
    Commented Aug 6, 2015 at 16:45
3
\$\begingroup\$

PHP, 278 bytes

A brute-force solution that uses a bunch of nested loops and a couple of tests.

$p=explode(',',$argv[$i=1]);for(;$i<=10;$i++)for($j=1;$j<=10;$j++)
for($k=1;$k<=10;$k++)if($j-$k)for($l=0;$l<3;$l++){$q=array_shift($p);
if($i*$q==$j*$p[0]+$k*$p[1]){$o=str_repeat('_',21);$o[10-$i]=$q;$o[10+$j]=$p[0];
$o[10+$k]=$p[1];echo($o."\n          ^\n");}array_push($p,$q);}

As always, put it into a file (let's name it seesaw.php), join the lines (split here for readability), put the PHP marker (<?php) at the beginning of the file (technically, it is not part of the program) and you're good to go.

An example of execution:

$ php seesaw.php 9,2,1
_________9_2_____1___
          ^
_________9__2__1_____
          ^
_________9_1__2______
          ^
________9_____2_____1
          ^
________9______2__1__
          ^
________9_____1__2___
          ^
________9___1_____2__
          ^
_______9_________1__2
          ^
____2______9_1_______
          ^
___2_______9___1_____
          ^
__2________9_____1___
          ^
_2_________9_______1_
          ^

It generates and displays all the solutions (without reflections), but it does not strip the duplicates (when the input values contain duplicates).

\$\endgroup\$
3
\$\begingroup\$

Julia, 154 bytes

f(a,b,c)=(x=replace(join(first(filter(p->p⋅[-10:-1,1:10]==0,permutations([a,b,c,zeros(Int,17)])))),"0","_");print(x[1:10]*"_"*x[11:20]*"\n"*" "^10*"^"))

Ungolfed + explanation:

function f(a,b,c)
    # Create a 20-element array of the input with 17 zeros
    z = [a,b,c,zeros(Int,17)]

    # Get the set of all permutations of z such that the dot product
    # of the permutation with the distances is 0
    d = filter(p -> p ⋅ [-10:-1,1:10] == 0, permutations(z))

    # Join the first element of d into a string and replace all of
    # the zeros with underscores
    x = replace(join(first(d)), "0", "_")

    # Print the output
    print(x[1:10] * "_" * x[11:20] * "\n" * " "^10 * "^")
end
\$\endgroup\$
2
\$\begingroup\$

C, 252 (214) bytes

Call with a,b,c as arguments on command line.

e=48;main(_,v,x,y,z,a,b,c)char**v;{char s[]="_____________________\n          ^";x=*v[1]-e;y=*v[2]-e;z=*v[3]-e;for(a=-1;a+11;--a)for(b=-10;b-11;++b)_=a*x+b*y,!b|b==a|_%z?0:(c=-_/z,c&c<11&c>-11?s[a+10]=x+e,s[b+10]=y+e,s[c+10]=z+e,puts(s),exit(0):0);} 

If main can be ommitted, byte count drops to 214 for a function.

a,b,c;f(x,y,z){char s[]="_____________________\n          ^";for(a=-1;a+11;--a)for(b=-10;b-11;++b)!b|b==a|(a*x+b*y)%z?0:(c=-(a*x+b*y)/z,c&&c<11&&c>-11?s[a+10]=x+48,s[b+10]=y+48,s[c+10]=z+48,puts(s),b=10,a=-b:0);}

Both use the same strategy of placing the first weight on the left, then scanning along possible second weight positions and calculating the third weight. This allows the removal of an inner loop.

\$\endgroup\$
1

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.