title: Hotter or Colder: Find the Treasure

text:
# Question
Title: Hotter or Colder: Find the Treasure
A certain children's game, often called "Huckle Buckle Beanstalk", is played with two players. Here is a brief description of how the game is played:

1. One player is designated the "hider", and the other the "seeker".
2. The seeker goes out of the room while the hider hides a small, pre-selected object, the "treasure".
3. The hider then attempts to look for the object while the seeker gives them helpful hints:
    * If the seeker is approaching the treasure, the hider will call out "warmer!"
    * If the seeker is moving away from the treasure, the hider will call out "cooler!"
4. Once the seeker finds the treasure, they announce that they have found it.

Your children want you to play this game with them, however, you are very busy answering questions on codegolf.SE instead. So, you decide to write a program to play the game with them. However, you want to use as little time as possible typing, so you try to make the program as little characters as possible.

We can define the room in which the game is played as a two dimensional toroidal square field. The coordinate `0,0` is the bottom left corner, and the coordinate `99,99` is the top right corner. The treasure is placed at some position `n,m` where `n` and `m` are both positive integers between 0 and 99 inclusive.

Your program will obtain input from the player using its inbuilt user input function (e.g. `prompt()`, `raw_input()`, etc.) If your chosen language *does not* have a user input function, take input from STDIN instead. The game will work as follows:

1. The program "hides" the treasure at a position `n,m`.
2. The program prompts the seeker to input an initial searching position. The input will come in the form `x y` where `x` and `y` are positive integers.
3. The program outputs "correct" if the initial searching position `x,y` is equal to the treasure's position `n,m` and terminates. Otherwise:
4. The program will prompt the seeker to move. The input comes in the form `a b` where `a` and `b` are *integers* that *may be negative*. This represents the *direction vector* that the seeker is moving in (`a` is the x direction and `b` is the y direction).
5. If the resultant position of the seeker is at the treasure, the program outputs "correct" and terminates. Otherwise:
6. The program outputs "cooler" if the seeker is moving away from the treasure, or "hotter" if they are moving towards the treasure.
7. Go to step 4.

The words "moving away" and "moving towards" may be ambigious. For this challenge, if the resultant position of the seeker after moving is closer to the treasure than their position before they were moving, they are moving towards the treasure. Otherwise, they are moving away. (Yes, this does mean that if the resultant and previous position are the same distance away, the program should output "cooler").

This is code golf, so shortest code wins. Ask questions if the specification is not clear.

# Answer
> 2 votes
## Javascript, 275 279

Not a winner by any means, but this should get things started. Uses a trick with `eval()` and defining `100` as a "constant" to shave off a few bytes. Ungolfed version below.

```
function D(){return Math.sqrt((x-n)*(x-n)+(y-m)*(y-m))}
H=100;
n=~~(Math.random()*H);m=~~(Math.random()*H);
P="s=prompt().split(' ')";
eval(P);
x=~~s[0];y=~~s[1];i=0;
while(x!=n||y!=m)
{
    if(i)alert(i>j?"hotter":"colder");
    i=D();
    eval(P);
    x=(x+~~s[0])%H;
    y=(y+~~s[1])%H;
    j=D()
}
alert("correct")

```

Edit: I fell victim to Javascript's string + number operations, hence why `D()` wasn't working properly. I also fixed a bug where "hotter" was displayed before "correct". This adds 4 bytes.

# Answer
> 2 votes
# Groovy - 278 266 262

**Golfed:**

```
def x,y,n,m,d,D=999,S=100,r=newScanner(System.in);n=Math.floor(Math.random()*S);m=Math.floor(Math.random()*S);while(true){x=r.nextInt();y=r.nextInt();d=Math.sqrt((x-n)**2+(y-m)**2);if(d==0){print"Correct";break;}else if(d<D){print"Cooler"}else{print"Hotter"}D=d}

```

**Ungolfed:**

```
def x,y,n,m,d
def dist = 99999
def r = new Scanner(System.in)
def S = 100
n = Math.floor(Math.random()*S)
m = Math.floor(Math.random()*S)
println "Treasure is at: $n $m"
while(true){
    x = r.nextInt()
    y = r.nextInt()
    d = Math.sqrt((x-n)**2+(y-m)**2)
    if(d == 0){print "Correct"; break;}
    else if(d > dist){print "Hotter" }
    else{print "Cooler"}
    dist = d
}

```

**Trial:**

```
-1 -1
Cooler 12 12
Cooler 14 14
Cooler 13 13
Hotter 15 15
Cooler 90 55
Cooler 95 -100
Hotter 95 83
Correct

```

# Answer
> 2 votes
# Python 3 - 238 bytes

---

Code:

```
from random import*
r=randint;a=100;X=r(0,a);Y=r(0,a);d=0;F=lambda:((X-x%a)**2+(Y-y%a)**2)**0.5;i=lambda:map(int,input().split());x,y=i()
while F():
 if d:print(["cooler","hotter"][d<D])
 D=F();Z,K=i();x+=Z+a;y+=K+a;d=F()
print("correct")

```

Ungolfed:

```
from random import*

treasure_x = random.randint(0,100)
treasure_y = random.randint(0,100)
distance = lambda:((treasure_x - x % 100) ** 2 + (treasure_y - y % 100) ** 2) ** 0.5
x, y = map(int, input("Coordinates in the form x y: ").split())
new_distance = 0

while distance():
    if new_distance:
        if new_distance < prev_distance:
            print("hotter")
        else:
            print("cooler")
    prev_distance = distance()
    dx, dy = map(int, input("Move in the form dx dy: ").split())
    x = (dx + x) % 100
    y = (dy + y) % 100
    new_distance = distance()

print("correct")

```

Sample run:

```
$ python hotter_colder.py
50 50
10 0
cooler
-10 0
hotter
-10 0
hotter
-10 0
hotter
-10 0
hotter
-10 0
cooler
5 0
hotter
1 0
hotter
1 0
hotter
1 0
hotter
1 0
hotter
1 0
cooler
-1 0
hotter
0 10
cooler
0 -10
hotter
0 -10
hotter
0 -10
cooler
0 5
hotter
0 1
hotter
0 1
correct

```

I won't say that my strategy in finding the treasure is particularity fast...

# Answer
> 2 votes
## Groovy - 343 chars

Derived somewhat from LittleChild's answer.

Golfed:

```
z=100
f={Math.floor(Math.random()*z)}
h={println it}
r=new Scanner(System.in)
i={r.nextInt()}
n=f();m=f();x=i();y=i();p=z;a=0;b=0
g={(Math.abs(it))**2};o={i,j->(j<0)?(((i+j)<0)?(((i+j)+z)%z):(i+j)):(i+j)%z};u={Math.sqrt g(n-x)+g(m-y)};d=u()
while(d>0.1){if(d<p){h "Hotter"}else{h "Cooler"};a=i();b=i();x=o(x,a);y=o(y,b);p=d;d=u()}
h "Correct"

```

Ungolfed:

```
z=100
f={Math.floor(Math.random()*z)}
h={println it}
r=new Scanner(System.in)
i={r.nextInt()}

n=f();m=f()
x=i();y=i()
p=z;a=0;b=0

g = {(Math.abs(it))**2}
o = {i,j->(j<0)?(((i+j)<0)?(((i+j)+z)%z):(i+j)):(i+j)%z}
u = {Math.sqrt g(n-x)+g(m-y)};d=u()

while (d>0.1) {
    if (d<p) { h "Hotter" } else { h "Cooler" }
    a=i();b=i()
    x=o(x,a);y=o(y,b)
    p=d;d=u()
}
h "Correct"

```

Sample run, where program emits the target for illustration. From my understanding of OP, the initial input is absolute, and subsequent inputs are relative. Also, the grid wraps around.

run A:

```
bash$ groovy X.groovy
goal 98.0 19.0
1 19
Hotter
-1 0
Cooler
-1 0
Hotter
-1 0
Correct

```

run B:

```
bash$ groovy X.groovy
goal 93.0 20.0
90 16
Hotter
2 2
Hotter
1 0
Hotter
0 -18
Cooler
0 -1
Cooler
0 -1
Hotter
0 -79
Hotter
0 1
Correct

```

# Answer
> 2 votes
## APL, 86 chars

```
h←?2⍴s←100⋄1{h≡n←s|s+⍵+⎕:⎕←"correct"⋄⍺:0∇n⋄⎕←(</+/⊃×⍨n⍵-¨⊂h)⌷"cooler" "hotter"⋄0∇n}0 0

```

Distance computation doesn't wrap around, but moves do.

**Ungolfed:**

```
h←?2⍴s←100                  ⍝ generate random starting point
1{                          ⍝ loop starting with ⍺←1 (1 if first loop) and ⍵←0 0 (position)
    n←s|s+⍵+⎕               ⍝ n←new position, ⍵ plus the move read from input, modulo 100
    n≡h: ⎕←"correct"        ⍝ check for end condition
    ⍺: 0∇n                  ⍝ if first loop, skip the rest and ask for a move again
    t←</+/⊃×⍨n⍵-¨⊂h         ⍝ t←1 if n is closer to h than ⍵ (squared distance)
    ⎕←t⌷"cooler" "hotter"   ⍝ output thermal gradient label
    0∇n                     ⍝ loop with new position
}0 0

```

**Example:**

```
⎕:
      22 33
⎕:
      2 6
hotter
⎕:
      0 1
cooler
⎕:
      0 ¯3
correct

```

# Answer
> 2 votes
# Python 2.7, 227

```
from random import*
r=randint
h=100
n=r(0,h)
m=r(0,h)
i=lambda:map(int,raw_input().split())
x,y=i()
d=lambda:(x%h-n)**2+(y%h-m)**2
e=d()
while e:
 p=e;a,b=i();x+=a;y+=b;e=d()
 if e:print e<p and'hotter'or'cooler'
print'correct'

```

I got the input function and the idea of applying the modulo in the distance calculation rather than the location update from matsjoyce's answer.

We only need distances for comparisions: Are we at the exact location? Are we closer than before? For both of these, we get the same result comparing the **squares** of the distances as we would comparing the distances. The square-root calculation required to get the actual distance is unnecessary.

Ungolfed:

```
import random

h = 100 # height (and width) of the square grid

# location of item
n = random.randint(0, h)
m = random.randint(0, h)

def input_pair():
    return map(int, raw_input().split())

x,y = input_pair()

def distance_squared():
    return (x % h - n)**2 + (y % h - m)**2

er = distance_squared()
while er:
    previous_er = er
    a,b = input_pair()
    x += a
    y += b
    er = distance_squared()
    if er:
        print 'hotter' if er < previous_er else 'cooler'
print 'correct'

```

Sample run:

```
50 50
20 0
hotter
20 0
cooler
-20 0
hotter
10 0
cooler
-10 0
hotter
-1 0
hotter
-1 0
hotter
-5 0
cooler
5 0
hotter
-1 0
cooler
1 0
hotter
1 0
cooler
-1 0
hotter
0 10
hotter
0 10
hotter
0 10
cooler
0 -5
hotter
0 -1
hotter
0 -1
hotter
0 -1
correct

```

# Answer
> 1 votes
# ECMAScript 6, 262

```
Z=100;A=Math.abs;P=(a,b)=>(q=Math.min(A(a-b),Z-A(a-b)),q*q);G=_=>prompt().split(' ');R=_=>new Date%Z;V=_=>P(X,I)+P(Y,J);I=R();L=G();X=+L[0];Y=+L[1];J=R();for(D=V();D;D=N)T=G(),X=(+T[0]+Z+X)%Z,Y=(+T[1]+Z+Y)%Z,N=V(),N&&alert(N<D?"hotter":"cooler");alert("correct")

```

Ungolfed:

```
Z=100;
M=Math.min;
A=Math.abs;
S=a=>a*a;
P=(a,b)=>S(M(A(a-b),Z-A(a-b)));
G=_=>prompt().split(' ');
R=_=>new Date%Z;
V=_=>P(X,I)+P(Y,J);
I=R();
L=G();
X=+L[0],Y=+L[1];
J=R();
for(D=V();D;D=N)
    T=G(),
    X=(+T[0]+Z+X)%Z,Y=(+T[1]+Z+Y)%Z,
    N=V(),
    N&&alert(N<D?"hotter":"cooler");
alert("correct")

```

# Answer
> 1 votes
## JavaScript ES6, Latest Firefox, ~~177~~ ~~173~~ 164 characters

Obviously, this cannot beat the APL one. That language is crazy! Maybe developed solely for code-golf questions :D :P

But here goes my solution in ES6 JavaScript. Run it in latest Firefox Nightly (or may be release version too) in the Web Console or Scratchpad.

```
A=a=>a*a;a=alert;g=v=>[x,y]=prompt().split(" ");r=v=>Math.random()*100|0;n=r(m=r(d=0));D=v=>A(n-x)+A(m-y);while(d=D(g(l=d)))l&&a(l<d?"hotter":"cooler");a("correct")

```

I'd like to skip the ungolfed version for now. Comment if you want to see the ungolfed version :)

**EDIT** : Golfed a lot! reduced 9 characters. Still seeing if further scope of golfing.

# Answer
> 1 votes
**C 193 176 171**

```
#define F x*x+y*y
x,y,a,b,d;main(){srand(time(0));x=rand();y=rand();while(scanf("%d %d",&a,&b),x-=a,x%=100,y-=b,y%=100,puts(F?F<d?"hotter":d?"cooler":"":"correct"),d=F);}

```

I'm sure there must be savings on the random number generation. Apart from that the key point is that reading in x & y is just treated as an offset from 0, so I only need one scanf. It does mean that I have to suppress printing hotter or cooler on the first iteration though.

Changes:

Put the location into x & y directly and then shift this back to (0,0) rather than put it in m & n and use x & y to search for it.

I realised that I was printing "hotter" and "correct" so I had to add an extra three characters here.

Rewritten the printing to put all conditions in it, saving an extra call to puts().

# Answer
> 0 votes
# Python 226

```
from random import randint as r
x=r(0,100)
y=r(0,100)
l=9**9
while True:
    i,j=map(int,raw_input().split())
    if x==i and y==j:
        print 'correct'
        break
    c=(x-i)**2+(y-j)**2
    if c<l:print 'warmer'
    elif c>l:print 'colder'
    l=c

```

That `import` looks really long and stupid, but it actually saves me 8 chars. `:D`

Example game:

```
50 50
warmer
50 75
colder
50 25
warmer
50 13
colder
50 37
colder
50 20
warmer
50 21
warmer
50 22
warmer
50 23
warmer
50 24
warmer
50 26
colder
50 25
warmer
25 25
colder
75 25
warmer
74 25
warmer
62 25
warmer
61 25
warmer
55 25
colder
56 25
warmer
57 25
warmer
58 25
warmer
59 25
warmer
60 25
warmer
61 25
warmer
62 25
colder
61 25
warmer
61 24
correct

```

# Answer
> 0 votes
# Sinclair /ZX Spectrum BASIC - 305 bytes

```
10 RANDOMIZE:LET o=99:LET a=INT(RND*99)+1:LET b=INT(RND*99)+1:PRINT a,b
20 INPUT "sx,sy:";c,d
30 LET g=SQR(ABS(a-c)^2+ABS(b-d)^2)
40 PRINT g'c,d
60 IF g=0 THEN PRINT "Found!":STOP
70 INPUT "mx,my:";x,y:LET c=c+x:let d=d+y
80 PRINT ("hotter" AND g<o)+("colder" AND g>o)
90 LET o=g:GOTO 30

```

As the Spectrum stores each keyword as one byte, it helps keep the size down. After it's been entered, found out the size with

```
print "bytes:";peek 23641+256*peek 23642-(peek 23635+256*peek 23636)+1

```

---
Tags: code-golf, game
---


title: Code-Golf Ascii Art Mini-Golf

text:
# Question
Title: Code-Golf Ascii Art Mini-Golf
# Intro

Let's play some mini-golf! The golf ball is represented by a `.` and the hole by a `O`. You want to get a hole in one on every hole, but you are not good at putting. In fact, you refuse to attempt putting diagonally! Only up, down, and to either side.

You plan to cheat by placing extra bumpers `\` and `/` so you can put the ball in with one shot. The ball bounces off of the bumpers at right angles, as shown in this picture.

Remember to call your shot! Tell us what direction you're putting.

---

# Holes

**1:** The first hole is easy, a straight shot! No bumpers needed to place here.

Input:

```
.         O

```

Output:

```
right
.         O

```

---

**2:** Another basic one, a short turn. The ball is hit off the bumper into the hole.

Input:

```
     .
O

```

Output:

```
left
/    .
O

```

or

```
down
     .
O    /

```

---

**3:** Some holes have bumpers already!

Input:

```
.   \O

```

Output:

```
right
.   \O
    \/

```

or

```
right
   / \
.  /\O

```

---

**4:** Some holes are overly complex!

Input:

```
    /  \  \    /
   /  . \  \  /
  /  /\/   /\ \  /
 /  /     /  \ \/
/  /   /\ \  /  \  /
\  \  /  \ \/    \/
      \  /          /
  /\   \//\ \      /
 /  \   /  \ \     \/
 \  /\  \  /  \     \
  \/  \  \/    \ O/  \
      /         \/

```

Output: (one possible solution, more exists)

```
down
    /  \  \    /
   /  . \  \  /
  /  /\/   /\ \  /
 /  /     /  \ \/
/  /   /\ \  /  \  /
\  \  /  \ \/    \/
/     \  /          /
  /\   \//\ \      /
\/  \   /  \ \     \/
 \  /\  \  /  \  /  \
  \/  \  \/    \ O/  \
      /  \      \/
                \   /

```

# Rules

* The **input** is the mini-golf hole on `STDIN`.
* The **output** is the direction you hit the ball and the mini-golf hole with newly placed bumpers on `STDOUT`.
* Existing bumpers cannot be moved.
* You can add any number of bumpers to solve a hole.
* Assume there are valid locations for the bumpers to be placed that will allow the course to be solved in one putt.
* The outputted hole may be bigger than the input.
* The input may be padded with trailing white space, but please specify in your answer if you do this.
* The output must look correct, but can have leading or trailing white space.
* Your program should work for any valid hole. Feel free to post your test cases too!

# Scoring

This is . Your score is the number of characters in your program. Lowest score wins!

# Answer
# Javascript (ES6) - 651 bytes

```
G=s=>{Q='\\';S=[[]];n=L=1;s.split(N='\n').map(t=>{j=S[L++]=[];l=t.length;n=n>l?n:l;k=1;t.split('').map(T=>{j[k++]=T})});S[O=L++]=[];n++;for(r=0;r<L;r++)for(c=0;c<=n;c++){v=S[r][c];if(!v)S[r][c]=' ';if(v=='.'){x=c;y=r}if(v=='o'){X=c;Y=r}}f=M=>{J=M?'.':'o';K=M?'o':'.';R=0;for(D=0;1;D++){R=D&4;D=D&3;c=e=D;g=M?X:x;h=M?Y:y;while(c!=K){c=S[h+=[-1,0,1,0][e]][g+=[0,1,0,-1][e]];e=c=='/'?(B=c,e^1):c==Q?(B=c,3-e):e;E=h*(h-O)?g*(g-n)?0:2:1;if(R&&c==' '){S[h][g]=Q;R=D=0;c=K}if(c==J||E){E&&(S[h][g]=(E+M)%2?Q:'/');H=M?E?H:(e+2)&3:D;return}}}};f(0);f(1);S[0][0]=S[O][n]='/';S[0][n]=S[O][0]=Q;return['up','right','down','left'][H]+N+S.map(t=>t.join('')).join(N)}

```

Creates a function `G` that accepts a string (golf course) as input and returns the requested putting solution. The input string may or may not have leading lines, trailing lines, and trailing whitespace. The output will not have leading or trailing whitespace.

Expanded code is:

```
G = s => {
    Q = '\\';
    S = [[]];
    n = L = 1;
    s.split( N = '\n' ).map( t => {
        j = S[L++] = [];
        l = t.length;
        n = n > l ? n : l;
        k = 1;
        t.split('').map( T => {
            j[k++] = T;
        } );
    } );
    S[O = L++] = [];
    n++;
    for( r = 0; r < L; r++ )
        for( c = 0; c <= n; c++ ) {
            v = S[r][c];
            if( !v )
                S[r][c] = ' ';
            if( v == '.' ) {
                x = c;
                y = r;
            }
            if( v == 'o' ) {
                X = c;
                Y = r;
            }
        }
    f = M => {
        J = M ? '.' : 'o';
        K = M ? 'o' : '.';
        R = 0;
        for( D = 0; 1; D++ ) {
            R = D & 4;
            D = D & 3;
            c = e = D;
            g = M ? X : x;
            h = M ? Y : y;
            while( c != K ) {
                c = S[h += [-1,0,1,0][e]][g += [0,1,0,-1][e]];
                e = c == '/' ? (B=c,e^1) : c == Q ? (B=c,3-e) : e;
                E = h*(h-O) ? g*(g-n) ? 0 : 2 : 1;
                if( R && c == ' ' ) {
                    S[h][g] = B;
                    R = D = 0;
                    c = K;
                }
                if( c == J || E ) {
                    E && (S[h][g] = (E+M)%2 ? Q : '/');
                    H = M ? E ? H : (e+2)&3 : D;
                    return;
                }
            }
        }
    };
    f(0);
    f(1);
    S[0][0] = S[O][n] = '/';
    S[0][n] = S[O][0] = Q;
    return ['up','right','down','left'][H] + N + S.map( t => t.join('') ).join( N );
}

```

The solver operates on the premise that any path from the ball (hole) will either

1. lead back to the ball (hole) again
2. lead to the hole (ball)
3. exit the course

We trace the ball's path in all four directions. If we find case 3, the problem is solved. If we find case 2, we mark the ball's exit location. If all four directions result in case 1, we convert the first non-bumper space along any trajectory to a bumper (if the problem is solvable, such a space is always guaranteed to exist) and try again. The bumper we convert to will have the same type as the last bumper our trajectory encountered\*. If the ball is still stuck in a loop, we repeat the process as many times as needed. If the problem is solvable, this procedure is guaranteed to eventually lead to outcome 2 or 3.

(\*Note that if we simply convert to a fixed bumper \[say, `\`\], there exist extremely contrived but nevertheless *possible* cases where a solution exists but we will fail to find it.)

We perform a similar trace from the hole, leading to either outcome 2 or outcome 3.

If both the ball trace and hole trace result in outcome 2, we place bumpers on the periphery of the course that link the two exit points (in fact, these periphery bumpers are placed regardless of the trace outcomes, to shorten the code). This completes the solution.

### Test Cases and Outputs

**In**

```
   /   \   / \ /\
   \\      /    \  \
       /     / o   /
   /   \       /
   \   .  \  \    \\
       /  /     \ \
       \          /
           \      /
 \ /\     /  \/  //\

```

**Out**

```
right
/   /               \
   /   \   / \ /\
   \\      /    \  \
       /     / o   /
   /   \       /
   \   .  \  \    \\
       /  /     \ \
       \          / /
           \      /
 \ /\     /  \/  //\
\                   /

```

**In**

```
  / \   / /    /  \    / \  /  \\ /
\   \ /  \  // \    \   /   /\   \
/ \   // \  //   \ \   \ /  / \\ \
 \  / \    /   \  \  / / \\ / /  //
/ /   /\ \\ //  / \   /  \ / \\ \ \
\   \  \ \ // \ /  /    \ \  /  / /
/ \ /   /  / \     / \ /\   /  \  /
\ /\  //\   .\  \ \ //\ /  \  / \ /
/ \/ \ /\ //\   /   \   / o// \ / \
/   / \    / \ / \\ / \   / \   \ \
/ /   / \  / \ //   \    / \/  /\/
   / \   / \  /   \\  / \    /\ / \
/ \/   \   /   \/  \   /  \    /\\
/ /\\ //\  / \  /\ /\   /  / \ / \/

```

**Out**

```
left
/                                   \
   / \   / /    /  \    / \  /  \\ /
 \   \ /  \  // \    \   /   /\   \
 / \   // \  //   \ \   \ /  / \\ \
  \  / \    /   \  \  / / \\ / /  //
 / /   /\ \\ //  / \   /  \ / \\ \ \
 \   \  \ \ // \ /  /    \ \  /  / /
 / \ /   /  / \     / \ /\   /  \  /
 \ /\  //\   .\  \ \ //\ /  \  / \ /
 / \/ \ /\ //\   /   \   / o// \ / \
 /   / \    / \ / \\ / \   / \   \ \
 / /   / \  / \ //   \    / \/  /\/
    / \   / \  /   \\  / \    /\ / \
 / \/   \   /   \/  \   /  \    /\\
 / /\\ //\  / \  /\ /\   /  / \ / \/
\         \                         /

```

**In**

```
/\/ \
\  \ \
 \ \\ \   o
  \ .\ \
   \ / /
    \ /

```

**Out**

```
down
/   \      /\
 /\/\\
 \ \\ \
  \ \\ \   o
   \ .\ \
    \ / /
     \ /
\           /

```
> 6 votes

---
Tags: code-golf, ascii-art
---


title: ASCII Art Code Generator

text:
# Question
Title: ASCII Art Code Generator
I have a program that generates formatted Brainfuck code. I run my program

```
./example "S"

```

and the output is

```
 +[>+
<
 +++
    ]
>--.

```

which prints S in Brainfuck.

Your objective is to write a program which accepts a string as input and outputs source code in another language which prints that string.

* The source code your program outputs must be formatted in such a way that it represents the string in ASCII art (printed horizontally, not vertically).
* The source code cannot contain the string (it may, however, contain letters that occur in the string, just not sequentially)

Otherwise,

Please title your submission with the language it is written in, the language it outputs, and the total size in bytes. Please include the output of your program when you enter the string UNCOPYRIGHTABLE.

Thanks!

# Answer
> 3 votes
# C --\> Brainfuck 556 Bytes

Excluding unnecessary whitespace. I could easily save another hundred by changing the font data in `d[]`from hex to a string in quotemarks.

```
i,j,s,t,u,v,w,h;
char a[99],b[9999],k,d[]={0x6F,0x3B,0x5A,0xD5,0x7A,0x6A,0x5B,0x2F,0xD0,0x57,0xA1,0x1B,0xCF,0x4F,0x5F,0x6E,0x6D,0x4E,0x79,0x3A,0x1F,0x95,0x9F,0xA6,0x3D,0x76};
f(int z){
  return d[a[j-1-t%(2*w*j)/w/2]-65]>>z&1?z=b[i*v/u],b[i++*v/u]=' ',z:' ';
}

main(){
  for(scanf("%s",a);a[j];i++)a[j]-k?k++,b[i]='+':(b[i]='.',t+=(0xE7572B70967DB>>(a[j]*2-130)&3)+5,j++);

  s=i/t+2;
  u=t*(s-1);
  v=i;
  i=0;

  w=2*s;h=2*s+1;
  for(t=2*w*h*j;t--;)putchar(
    t%(2*w*j)?
      t/2/w/j%s?

        t%s||!(t/4%s)?' ':f(t/s%4/2+t/2/w/j/s*2|7*(t/s%4==2))
      :(
        (t%s)&&(t/s+1&2)?f(4+t/2/w/j/s):' '
      )
    :10  //newline
  );

}

```

This uses a calculator font (for low entropy, only one byte per letter) and a very naive Brainfuck compiler inspired by https://codegolf.stackexchange.com/a/35801/15599 (except I use plus instead of minus.) The first `for` loop compiles the text in `a` to the string `b`, and also calculates the number of strokes required to draw the formatted code, using the 13-digit hex magic number (all characters are 5-8 strokes.)

Given the total program length and the stroke count, the number of characters per stroke is calculated (this can be very small if the characters are the same or in ascending order, and very large if the characters are in descending order.)

Most of the rest of the program is dedicated to deciding whether whitespace or one of the strokes needs to be printed. If the cursor is over a stroke square, the function `f`is called with the number of that stroke as an argument. It returns a space if that stroke is not required for the current letter, or a character from the program if it is. Because the number of characters required to complete the ASCII art may be more than the characters in the program, occasionally a space is inserted, hence the calculation `b[i * v/u]`.

There are four single strokes and four double strokes in the font, numbered as follows, which are either present or absent, depending on the letter.

```
 6666 6666
3    7    2
3    7    2
3    7    2
3    7    2
 5555 5555
1    7    0
1    7    0
1    7    0
1    7    0
 4444 4444

```

**Output**

Test at http://copy.sh/brainfuck/

ABC

```
 + ++ +++                                ++++ + ++
+         +         +
+         +         +                   +
+                   +                   +
+         +         +
 ++++ + ++           +++  ++++
+                   +         +         +
+         +                   +         +
+         +         +                   +
+         +         +         +
                     ++++ + ++           ++.  +.+.

```

DEF

```
 + ++ ++ +           ++++  +++           ++ + ++++
          +         +                   +
     +    +                             +
     +    +         +                   +
          +         +                   +
                     ++ + +++            ++++ + ++
     +    +         +
     +    +         +                   +
     +              +                   +
     +    +         +
 ++++ + ++           ++.  +.+.

```

GHIJK

```
 + + +++                         ++  +++         +++  ++
+               +       +           +                               +
+               +       +           +                   +
+               +       +           +                   +           +
                  ++ +++                                         + + +++
+       +       +                   +           +       +           +   +
+               +       +           +           +       +           +
+       +       +       +           +           +                   +   +
 +++ + +                         ++. +.          +.+ .+.

```

LMNOP

```
                 + + +++         + + +++         + + +++         + + +++
+                   +   +       +       +       +               +       +
+               +   +           +       +       +       +       +
+               +   +   +       +               +       +       +       +
                                                                 + + +++
+               +   +   +       +       +               +       +
+       +       +       +       +       +       +       +
+       +       +   +   +               +       +       +       +
 + . +.+                                         . + .+.

```

QRSTU

```
 + + +++         +++ +++         +++ ++
+       +       +       +       +               +               +       +
+       +       +       +       +               +               +
+       +       +       +       +               +               +       +
 +++ +++                         + + +++         +++ +++
        +       +                       +       +               +
        +       +                       +       +               +       +
        +       +                       +       +               +       +
                                 +++  ++         +++ .+.         +.+ .+.

```

VWXYZ

```
                                                                + + +++
   +   +       +   +   +               +       +       +               +
   +   +       +   +   +           +           +       +               +
   +   +       +   +   +           +           +       +               +
                                +++ +++         + + +++         +++ ++
   +   +       +   +   +       +   +                   +       +
   +           +   +   +       +   +                   +       +
   +   +           +   +       +   +                   +       +
+++ + +         +++ +++                         ++  .+.         +.+ .+.

```

**COPYABLE**

with most strings with letters in random order (not ascending) the letter size is much larger, and the letters look much better. Unfortunately the file sizes get quite large. I cannot upload the full word UCOPYRIGHTABLE here, COPYABLE is about the longest word I am allowed.

```
        + +++++++++ +++++++++++                         + +++++++++ +++++++++++                         ++ ++++++++ +++++++++++                                                                         +++ +.+++++ +++++++.+.+                                                                                ++++ ++++.+ +++++++++++
       +                                               +                       +                       +                       +                                               +                       +                       +                       +                                               +                                               +
       +                                               +                       +                       +                       +                       +                       +                       +                       +                       +                                               +                                               +
       +                                               +                       +                                               +                       +                       +                       +                       +                       +                                               +                                               +
       +                                               +                       +                       +                       +                       +                       +                       +                       +                       +                                               +                                               +
       +                                               +                                               +                       +                       +                       +                       +                       +                       +                                               +                                               +
       +                                               +                       +                       +                       +                       +                       +                       +                       +                       +                                               +                                               +
       +                                                                       +                       +                       +                       +                       +                       +                       +                       +                                               +                                               +
       +                                               +                       +                       +                       +                       +                       +                       +                       +                       +                                               +                                               +
                                                       +                       +                       +                       +                       +                       +                       +                       +                       +                                               +                                               +
       +                                               +                       +                       +                       +                       +                       +                       +                       +                       +                                               +
       +                                               +                       +                       +                       +                       +                       +                       +                       +                       +                                               +                                               +
                                                                                +++++++++ + +++++++++++                         ++++++++++  +++++++++++                         +++++++++++  ++++++++++                         +++++++++++ + +++++++++                                                                         ++++++++++. +. ++++++++
       +                                               +                       .                       +                                                                       +                       +                       +                       +                       +                       +                       +                       +
       +                                               +                                               +                                                                       +                       +                       +                       +                       +                       +                       +                       +
       +                                               +                       +                       +                                                                       +                       +                       +                       +                       +                       +                       +                       +
                                                       +                       +                       +                                                                       +                       +                       +                       +                       +                       +                       +                       +
       +                                               +                       +                       +                                                                       +                       +                       +                       +                       +                       +                       +
       +                                               +                       +                       +                                                                       +                       +                       +                       +                       +                       +                       +                       +
       +                                               +                       +                       +                                                                       +                       +                       +                       +                       +                       +                                               +
       +                                               +                       +                       +                                                                       +                       +                       +                       +                       +                       +                       +                       +
       +                                               +                       +                       +                                                                       +                       +                       +                       +                       +                                               +                       +
       +                                               +                       +                       +                                                                       +                       +                       +                       +                       +                       +                       +                       +
       +                                               +                       +                       +                                                                       +                       +                       +                       +                                               +                       +                       +
        +++++++++++ +++++++ +++                         +++++++++++ ++++++++ ++                                                                         +++++++++++ +++++++++ +                                                                         +++++++++++ ++++++++++                          +++++++++++ +++++++++++                          ++++++++++ ++++++++++.

```

# Answer
> 9 votes
# Perl → Befunge, 868 bytes

OK, I'll get the ball rolling. This could be golfed down a bit more, but my head is starting to hurt...

```
$_=" f,j f,jjj f,lgdlH,b >llb ,l,b lb ,lb , f,j f j f >>l>,lb ,9vb >lb,Hlb,H>vb >999*+,
mg8Hg8Ha8c8g8Hgb8Hab8,8k/ 8Ha8Hi /H8HgH8g8k >H9ghgH9b 'bhbhgH9ghg9+gH9ga//
ma8Hg8Ha8c8ahgbhabhh /bhah VdhibHH9ghb >H9ghgH9abhbhgH*g9+g ii /b>l,^b //
>H^>>Hned*angne ned* eneknabnn<b nangn idH*gned*gneb*>>,b *kngH5g*6 Adb><aha//b
H*g2HgH3a4Hg5Ha6c7gHHgb1Hab2+3H ib4Ha5Hg6kiHH7g8c, id1H iabHk3k4+g >+ ,^>^dd 7/ ib *k //b
+1g+HgH+g+Hg+Ha+c+g,Hgb+kk >^+ki +Ha+Hg+HgH+g+cki'+ki ,gk+k>^gbHc^H 9*gb8+b//a
^<b ^>^ebe^'>^e >^e>>^a >^>> >^gd>^ke> >^b '>^e>>^g>^g e^ >^a >^~'i>^b i >2+^b >^b e>gHaV V >^gb>^bHHHHHH";
s/n/*H/g;s/m/H8g8HgH8/g;s/l/v>/g;s/k/Hb/g;s/j/f>,/g;s/i/\\/g;s/h/9H/g;s/g/bd/g;s/f/ve/g;s/e/>>>/g;s/d/ H/g;s/c/HaH/g;s/b/  /g;s/a/    /g;@f=split$/;
@s=split('',$ARGV[0]);foreach$r(0..6){for($i=0;$i<@s;$i++){print substr($f[$r],(ord($s[$i])-65)*6,6).$"}print$r?'':' @',$/}

```

## Examples:

The shorter examples can be copy-pasted into online interpreters like this one, but **UNCOPYRIGHTABLE** appears to result in a program that is too long for all the online interpreters to handle.

```
$ perl bf.pl ABCDEFGHI
 v>>>, v>>>>,  v>>>, v>>>>, v>>>>, v>>>>,  v>>>, v>   H  Hv>H,  @
H8   H 8H   H H8   H 8H   H 8H     8H     H8   H 8H   H   8H
H8   H 8H   H H8     8H   H 8H     8H     H8     9H   H   9H
>H^>>H *H>>>  H*     *H   H *H>>>  *H>>>  H* >>> *H>>>H   *H
H*   H 2H   H H3     4H   H 5H     6H     H7   H HH   H   1H
+1   H +H   H H+   H +H   H +H     +H     H+   H ,H   H   +H
^<   ^ >^>>>   >>>^' >^>>>  >^>>>> >^      >^>>  >^   H  H>^H

$ perl bf.pl JKLMNOPQR
   >v> v>   , v>,    v>   , v>   ,  v>>>, v>>>>,  v>>>  v>>>>,  @
    8, 8H  /  8H     8H\ /H 8H   H H8   H 8H   > H9   H 9H   H
    9H 9H /   9H     9H V H 9H\  H H9   H 9H   > H9   H 9H   H
    *H *H<    *H     *H   H *H \ H H*   H *H>>>  H*   H *H>>>
    2+ 3H \   4H     5H   H 6H  \H H7   H 8H     H, \ H 1H \
H   >^ +H  \  +H     +H   H +H   H H+   H +H     HH  \' +H  \
 >>>>  >^   ' >^>>>> >^   H >^   H  >>>^  >^      >^~'\ >^   \

$ perl bf.pl STUVWXYZ
 v>>>  >>v>>, v>   , 9v   > v>  ,H v>  ,H >v   > 999*+,  @
H9   '   9H   9H   H H9   H 9H   H 9+   H H9   H     //
H9       9H   9H   H H*   H 9+   H  \\ /   >v>,^    //
 *>>,    *H   *H   H H5   H *6 A H   ><     9H     //
    HH   3H   4+   H  >+ ,^ >^ H H  7/ \    *H    //
,   HH   +H   >^   H   HH     H^H  9*   H   8+   //
 >2+^    >^    >>>>    HH     V V  >^   H   >^   HHHHHH

$ perl bf.pl UNCOPYRIGHTABLE
v>   , v>   ,  v>>>,  v>>>, v>>>>, >v   > v>>>>,  Hv>H,  v>>>, v>   H >>v>>,  v>>>, v>>>>, v>,    v>>>>,  @
9H   H 8H   H H8   H H8   H 8H   > H9   H 9H   H   8H   H8   H 8H   H   9H   H8   H 8H   H 8H     8H
9H   H 9H\  H H8     H9   H 9H   >  >v>,^ 9H   H   9H   H8     9H   H   9H   H8   H 8H   H 9H     8H
*H   H *H \ H H*     H*   H *H>>>    9H   *H>>>    *H   H* >>> *H>>>H   *H   >H^>>H *H>>>  *H     *H>>>
4+   H 6H  \H H3     H7   H 8H       *H   1H \     1H   H7   H HH   H   3H   H*   H 2H   H 4H     5H
>^   H +H   H H+   H H+   H +H       8+   +H  \    +H   H+   H ,H   H   +H   +1   H +H   H +H     +H
 >>>>  >^   H  >>>^'  >>>^  >^       >^   >^   \  H>^H   >^>>  >^   H   >^   ^<   ^ >^>>>  >^>>>> >^>>>>

```

---

### Note:

The `@` character at the end of the first line of output tells Befunge to stop running. Without it, the program would keep repeating the same word forever.

# Answer
> 3 votes
## C → Brainfuck, 855 bytes

Some newlines added to improve readability. Notice it segfaults on lowercase letters and symbols. Test the output here.

```
#define p putchar
#define V(x) c=v[1][x]-65;
l[]={96,48,24,12,66,98,60,90,6,70,102,54,118,14,62,126},e[]={2863659686,
3937331886,1787332774,3937053358,4170115215,2291067023,1789692070,2863659690,
1646404134,1778384896,2864569258,4169697416,1145534458,1165457300,1789569702,
2291051182,1823124134,2863573678,1778804902,572662319,1789569706,648719018,
2943841348,2863033002,572680874,4164034831},a[]={36,36,24,34,30,26,29,36,20,20,
30,20,28,26,32,28,33,34,28,20,32,30,28,32,24,24},r,o,j,k,c,z;char*b[]={
"-[+>+<[+<]>]>+","-[+[>---<<]>+]>-","+[>+<+++++++]>",">+++[[-<]>>--]<",
"+[>+<+++]>----","+[>+<+++]>","-[+[+<]>>+]<+"};main(i,v)char**v;{for(;r<8;r++){
for(i=0;v[1][i];i++)for(o=0;o<8;o++){V(i)if((l[(e[c]>>(4*r))&15]>>o)&1){V(j)
if(k==a[c]){j++;k=0;}V(j)z=k-strlen(b[c/4]);if(z<0)p(b[c/4][k]);else{c=(c%4)-z;
!c?p(46):(c>0?p(43):p(62));}k++;}else p(32);}p(10);}}

```

## Examples

It looks a lot nicer on a terminal :(

```
$ ./art ABCDEFGHI

  -[+>   +<[+<    ]>]>   +.>>>   >>>>>>  >>>>>>   >>>>   >>  -[   +>+<
 [+  <]  >]  >+  +.  >>  >>  >>  >>      >>      >>  >>  >>  >>    >>
 -[  +>  +<  [+  <]      >]  >+  ++      .>      >>      >>  >>    -[
 +>+<[+  <]>]>   ++      ++  .>  >>>>>   >>>>>   >>      >>>-[+    [>
 ---<<]  >+]>-   .>      >>  >>  >>>>>   >>>-[   +[ >--  -<<]>+    ]>
 -+  .>  >>  >>  >>      >-  [+  [>      --      -<  <]  >+  ]>    -+
 +.  >>  >>  >>  >>  >>  -[  +[  >-      --      <<  ]>  +]  >-    ++
 +.  >>  >>>>>    >>>>   >>>>>   +[>+<+  ++       ++++   ]>  .>   >>>>

 $ ./art JKLMNOPQR

     +[  >+  <+  ++      ++  ++  ]    >   +.>>   >>+[>    +<++   +++++
     ]>  ++  .>  >>      >>>>>>  >>   >  >+  [>  +<  ++  ++  ++  +]  >+
     ++  .> >>   ++      + [[ -  < ]> >  --  ]<  .>  >>  >>  >>  >>  >>
     >>  +++     [[      - <] >  > -- ]  <+  .>  >>  >>  >>  >>  >+  ++
     [[  -<]     >>      - -] <  + +. >  >>  >>  >>>>>   >>  >>  >+++[
     [-  <] >>   --      ]    <  + ++ .  >>  >>  >>      >>  >+  [>  +<
 ++  +]  >-  --  -.      >    >  >   >>  >>  >>  >>      >> >>>  >>  +[
  >+<+   ++  ]>  ----+.  >    >  >    >   >>>>   >>       >>>>   >>  >>

$ ./art STUVWXYZ

  +[>+   <+++]>  --  --  ++  .>  >    >  >>  >>  >>  >>  +[>+<+
 ++  ]>    --    --  ++  +.  >>  +    [  >+  <+  ++  ]>      .>
 >>        >>    >>  >>  >>  >>  >    >  >>  >>  >>  +[     >+
  <+++     ]>    +.  >>  >>  >>  > >> >   >>>>    >>>>     +[
  >+<+     ++    ]>  ++  .>  >>  > >> >   >>>>     >>      >>
     +[    >+    <+  ++  ]>  ++  + .> >  >>  >>    >>     >>
 >>  >>    >>    >>  -[   +[+<   ]>>+]<  +.  >>    >>    >>
  >>>>     -[     +[+<     ]>    >+  ]<  ++  .>    >>    >>>>>>

```

And finally,

```
$ ./art UNCOPYRIGHTABLE

 +[  >+  <    +   ++]>    .>>>   >>>>>   >>  >>  >>>>>    >>>>    >+++   [[  -<  ]>>--]   <+.>   >>>>>   >>      >-[+>+
 <[  +<  ]>   ]  >+  ++  .>  >>  >>  >>  >+  ++  [[  -<    ]>    >-  -]  <+  +.    >>    >>  >>  >>  >>  >>      >>
 >+  ++  [ [- <  ]>      >-  -]  <+  ++  .>  >>  >>  >>    >>    -[      +[  +<    ]>    >+  ]<  +.  >>  >>      >>
 >>  >>  + [> +  <+      ++  ]>  --  --   +.>>   >>  >>    >>    >>      >>>>>>    >>    +[>+<+  +++++   +]      >.>>>
 >>  -[  + [> -  --      <<  ]>  +]>-+     +.    >>>>>     >>    >> >-[  +[>---    <<    ]>+]>-  +++.>   >>      >>>>>
 >>  >>  > >> >  +[      >+  <+  ++        ]>    --  --    ++    +.  >>  -[  +>    +<    [+  <]  >]  >+  .>      >>
 >>  >>  >   >>  >>  >>  >>  >>  >>        >-    [+  >+    <[    +<  ]>  ]>  ++    .>    >>  >>  >>  >>  >>      >>
  >>>>   >    >   >+[>    +<++   ++        ++    +]  >+   ++.>    >-[+   [>  --    -<    <]  >+  ]>-.>   >>>>>>  >>>>>>

```

---
Tags: code-golf, ascii-art
---


title: Laser Mirror Portal Party

text:
# Question
Title: Laser Mirror Portal Party
A 2D board *will* contain the following objects:

* `^`,`>`,`v`, or `<`: A laser emitter facing up, right, down, or left respectively. There may be more than one. Lasers will travel in a straight line in empty space (empty space is represented with a dot `.`). Lasers do not pass through emitters.
* `*`: A target. Lasers *pass through* targets. There may be more than one.

The board *may* also contain the following objects:

* `@`: A solid wall. The laser will not pass through here.
* `\`: A *left-leaning* reflector. Changes the direction of lasers according to the following table:

```
Direction laser is travelling     Direction of laser after hitting reflector
Up                                Left
Right                             Down
Down                              Right
Left                              Up

```

It should be pretty intuitive as to how the reflectors work. Just imagine them as an actual two-sided mirror and the directions should be clear.
* `/`: A *right-leaning* reflector. Changes the direction of lasers according to the following table:

```
Direction laser is travelling     Direction of laser after hitting reflector
Up                                Right
Right                             Up
Down                              Left
Left                              Down

```
* `1`,`2`,`3`...`9`: A *portal*. The number indicates the channel of the portal - there will be exactly two portals of the same channel (for instance, there won't be three `1`'s). The portal changes the *position* of lasers to the position of the other portal of the same channel. For instance:

```
>     1     @     1     *

```

The laser will hit the target because when it hits the first `1`, it is teleported to the second `1` on the other side. Lasers retain the same direction that they were in before.

A portal will not teleport the laser to a portal of a different channel (i.e. a `1` won't teleport the laser to a `9`.

Your program will recieve a 2D representation of the board as input. The board will always be rectangular shaped. The output should be `True` if all the targets have lasers passing through them, or `False` otherwise.

Here are some test cases:

1. Input

```
>....\
..*...
>./../
..*...

```

Output

```
True

```
2. Input

```
>..........\
1........../
2..........1
3..........2
4..........3
5..........4
6..........5
7..........6
8..........7
9..........8
*..........9

```

Output

```
True

```
3. Input

```
>.@............*
>..@...........*
>...@..........*
>....@.........*
>.....@........*
>...*..@........
>.......@......*

```

Output

```
False

```
4. Input

```
../\.
>./**

```

Output

```
False

```
5. Input

```
/.......*.......\/3.....
@..............//\.\....
*.............2\.1\/\...
\..............///.....<
.........*...//\\/.....\
>.............\.1.///.4.
4.......*/...\2\/3/\/..^

```

Output

```
True

```
6. Input

```
vvvvvvvvvvvvvvvvv
\\\\\\\\\\\\\\\\\
/////////////////
\\\\\\\\\\\\\\\\\
/////////////////
\\\\\\\\\\\\\\\\\
/////////////////
*****************

```

Output (note the target at the far right)

```
False

```

# Answer
## Python, ~~310~~ ~~302~~ ~~287~~ ~~278~~ ~~277~~ 260

Not radically different than the existing Python post, but has one or two noteworthy tricks, I think. ~~It also handles "non-terminating" input, such as `1>1`.~~ **EDIT**: Oops! emitters block lasers.

```
def t(b):
 w=len(b[0])+1;B=list('@'*w+'@'.join(b));i=l=len(B);C="<>^v@"
 while i:
    j=l-i;i-=1;d=C.find(B[j]);c='.'
    while c not in C:
     if'+'>c:B[j]='.'
     if'0'<c<C:j=(B*2).index(c,j+1)%l
     elif'.'<c:d^=2+(c<C)
     j-=[1,-1,w,-w,j][d];c=B[j%l]
 return'*'not in B

```

`t` takes a list of strings (the input lines) and returns a boolean result.

Here's a nice gif of the code being golfed down:

**EDIT**: Awsome gif courtesy of Will. Thanks Will!
> 8 votes

# Answer
## Perl, 647

This is my first ever attempt at code-golf, and I'm a bit embarrassed I didn't even beat the C# score, but I thought it would be interesting (or fun, or just masochistic) to do the entire thing as a series of regex substitutions. (I also thought it would be fun to brush up on my Perl, but by the end I was deeply regretting not implementing it in Ruby or Python.)

I haven't done a lot of testing, but I *think* it should handle every case.

The grid is input via STDIN. There must be at least one newline in the input (i.e. a single row without a newline won't work).

```
%s=(d,'[|+#$vk%ZX]',u,'[|+#$^W%KX]',r,'[-G+#>k%KX]',l,'[-G+#<W%ZX]');%o=(d,'[-.*G/k\\\\Z',u,'[-.*G/W\\\\K',r,'[|.*$\\\\/kK',l,'[|.*$\\\\/ZW');for$d(d,u,r,l){$o{$d}.='123456789qwertyuio]'}%u=(d,'.|-+*$G#/Wk%\KZX',u,'.|-+*$G#/kW%\ZKX',r,'.-|+*G$#/Wk%\ZKX',l,'.-|+*G$#/kW%\KZX');@q=split//,"qwertyuio";local$/;$_=<STDIN>;for$i(1..9){$m{$i}=$q[$i-1];$m{$m{$i}}=$i;s/$i/$m{$i}/e}/.*?\n/;$l='.'x((length$&)-1);do{$c=0;for$d(d,u,r,l){%p=(d,"(?<=$s{d}$l)$o{d}",u,"$o{u}(?=$l$s{u})",r,"(?<=$s{r})$o{r}",l,"$o{l}(?=$s{l})");%h=split//,$u{$d};$c+=s!$p{$d}!$h{$&}||($v=$&,($o{$d}=~s/$v// && $s{$d}=~s/]/$m{$v}]/),$v)!es}}while($c);print/\*/?"False\n":"True\n"

```

Explanation: the code iteratively updates the grid string as the lasers pass through it. `-` represents a horizontal laser, `|` a vertical laser, `+` crossed lasers, `K` a `\` mirror with a laser bouncing off the top, `k` a `/` mirror with a laser bouncing off the bottom, `Z` a `\` mirror with a laser bouncing off the bottom, and `W` a `/` mirror with a laser bouncing off the top. `%` is a `/` mirror with lasers on both sides, while `X` is a `\` mirror with lasers on both sides. (These are case sensitive. I tried to pick letters that look somewhat appropriate--for instance, `k` and `K` are somewhat obvious choices--but unfortunately the effect really isn't that helpful. I should really put this info into a table, but I'm exhausted right now.)

Handling portals in the same way (i.e. assigning each digit a set of extra characters based on the possible input/output laser positions) would require 144 characters (including the original 9), so instead, when a laser hits an "input" portal, I add the "output" portal character to the set of characters that emit a laser in the proper direction. (This does require differentiating between input and output portals; I used the letters `qwertyuio` for this.)

Somewhat un-golfed, with print statements so you can see the substitutions happening (each substitution represents one "round" of laser-progression), and with the `g` flag added to the main `s///` so that it doesn't take so many iterations:

```
# Throughout, d,u,r,l represents lasers going down, up, left, or right
# `sources` are the character classes representing laser "sources" (i.e. any
# character that can, on the next round, cause a laser to enter the space
# immediately adjacent to it in the proper direction)
%sources=(d,'[|+#$vk%ZX]',u,'[|+#$^W%KX]',r,'[-G+#>k%KX]',l,'[-G+#<W%ZX]');
# `open` characters will not block a laser
%open=(d,'[-.*G/k\\\\Z',u,'[-.*G/W\\\\K',r,'[|.*$\\\\/kK',l,'[|.*$\\\\/ZW');
# One of each portal is changed into the corresponding letter in `qwertyuio`.
# At the start, each portal is 'open' and none of them is a source.
for$d(d,u,r,l){$open{$d}.='123456789qwertyuio]'}
# A mapping of 'open' characters to the characters they become when a laser
# goes through them. (This is used like a hash of hashes; see the assignment
# of `%h` below.)
%update=(d,'.|-+*$G#/Wk%\KZX',
    u,'.|-+*$G#/kW%\ZKX',
    r,'.-|+*G$#/Wk%\ZKX',
    l,'.-|+*G$#/kW%\KZX');
@q=split//,"qwertyuio";
local$/;$_=<STDIN>;
for$i(1..9){
    $m{$i}=$q[$i-1];
    $m{$m{$i}}=$i;
    s/$i/$m{$i}/e}
print "After substituting portals:\n";
print;
print "\n";
# Find the number of characters in each line and create a string of `.`'s,
# which will be used to correlate characters above/below one another in the
# grid with each other.
/.*?\n/;
$l='.'x((length$&)-1);
do{
    $changes=0;
    for$d(d,u,r,l){
        # `patterns` is a mapping from each direction to the regex representing
        # an update that must occur (i.e. a place where a laser must progress).
        # Each pattern is either a lookahead or lookbehind plus the necessary
        # "open" character class.
        %patterns=(d,"(?<=$sources{d}$l)$open{d}",
            u,"$open{u}(?=$l$sources{u})",
            r,"(?<=$sources{r})$open{r}",
            l,"$open{l}(?=$sources{l})");
        %h=split//,$update{$d};
        # Match against the pattern for each direction. Note whether any
        # matches were found.
        $changes+=s!$patterns{$d}!
            # If the "open" character for a map is in the `update` map, return
            # the corresponding value. Otherwise, the "open" character is a
            # portal.
            $h{$&} || ($v=$&,
                        # For portals, remove the input portal from the
                        # proper "open" list and add the output portal to
                        # the proper "source" list.
                       ($open{$d}=~s/$v// && $sources{$d}=~s/]/$m{$v}]/),
                       $v)
                    # This whole substitution should allow `.` to match
                    # newlines (see the definition of `$l` above), and the
                    # replacement must be an expression rather than a string
                    # to facilitate the portal logic. The `g` allows multiple
                    # updates per "frame"; it is left out of the golfed code.
                    !egs
    }
    # Print the next "frame".
    print;
    print "\n";
# Continue updating until no "open" spaces are found.
}while($changes);
# Print whether `*` is still present in the input.
print/\*/?"False\n":"True\n"

```
> 7 votes

# Answer
### Python 338 *351*

```
def t(b):
 L=len;w=L(b[0])+3;b=list("@"*w+"@@".join(b)+"@"*w);w-=1;I=b.index
 for i in range(L(b)):
  c=b[i];d={"^":-w,"<":-1,">":1,"v":w}.get(c)
  if d:
   while c!='@':
    i+=d;c=b[i]
    if c=='*':b[i]='.'
    elif c in '/\\':d={-w:-1,w:1,1:w,-1:-w}[d]*(-1 if c=='/' else 1)
    elif c>'0':i+=I(c)-i or I(c,i+1)-i
 return "*" not in b

```

My unminified version actually plots the laser paths on the board, which is pretty:

```
>-+--\
..X..|
>-/--/
..X...

>----------\
1----------/
2----------1
3----------2
4----------3
5----------4
6----------5
7----------6
8----------7
9----------8
X----------9

>-@............*
>--@...........*
>---@..........*
>----@.........*
>-----@........*
>---X--@........
>-------@......*

/-------X+------\/3.....
@........|.....//\+\....
X........|....2\+1\/\...
\--------+----+///+++--<
.........X...//\\/+++--\
>--------+---+\+1+///-4|
4-------X/...\2\/3/\/..^

vvvvvvvvvvvvvvvvv
\\\\\\\\\\\\\\\\\
/////////////////
\\\\\\\\\\\\\\\\\
/////////////////
\\\\\\\\\\\\\\\\\
/////////////////
XXXXXXXXXXXXXXXX*

def debug(board,x,y):
    emit_dir = {
        "^":    ( 0, -1),
        "<":    (-1,  0),
        ">":    ( 1,  0),
        "v":    ( 0,  1),
    }
    class PortalException(Exception): pass
    xdir, ydir = emit_dir[board[y][x]]
    while True:
        # print "step (%d, %d) (%d, %d)" % (x, y, xdir, ydir)
        x += xdir
        y += ydir
        if y < 0 or y >= len(board) or x < 0 or x >= len(board[y]):
            return
        ch = board[y][x]
        if ch == '/':
            xdir, ydir = -ydir, -xdir
        elif ch == '\\':
            xdir, ydir = ydir, xdir
        elif ch in '@^><v':
            return
        elif ch == '*':
            board[y] = board[y][:x] + 'X' + board[y][x+1:]
        elif ch in '.-|':
            ch = ('-' if xdir else '|') if ch == '.' else '+'
            board[y] = board[y][:x] + ch + board[y][x+1:]
        elif ch in '123456789':
            try:
                for r in range(len(board)):
                    for c in range(len(board[r])):
                        if board[r][c] == ch and (r != y or c != x):
                            x, y = c, r
                            raise PortalException()
                raise Exception("could not find portal %s (%d,%d)" % (ch, x, y))
            except PortalException:
                pass

```
> 6 votes

# Answer
# C# - ~~515~~ ~~414~~ 400 bytes

Complete C# program, no nice output like Will's. Works by following the laser path for each emitted individually, and keeping an array of which cells we've visited, so that we can check that we've visited all the stars at the end. *Edit: striped a large number of bytes by making everything 1D and by using a char instead of an int to store the current char*

w0lf reminded me that I had an under utilized for-loop right in the middle of my code, so I figured I'd better make one last effort and put it to work, and now I'm down to the absolute minimum number of curly braces. I won't pretend to like the collapsing of the second for loop, the code is horribly disorderly now, but it saved a few bytes. In the process I re-wrote the portal handling. I also found a shorter method for performing the "move" with nested rather than aggregated conditional operation.

Golfed code:

```
using C=System.Console;class P{static void Main(){var S=C.In.ReadToEnd().Replace("\r","");int W=S.IndexOf('\n')+1,l=S.Length,i=l,d,m,n;var M=new int[l];for(char c;i-->0;)for(d="^<v>".IndexOf(c=S[m=i]);c>14&d>-1;d=(m+=d==2?W:d>0?d-2:-W)>=0&m<l&&"@^<v>".IndexOf(c=S[m])<0?d:-1)for(d=c==47?3-d:c==92?d^1:d,M[n=m]=1;c%49<9&&(m=S.IndexOf(c,m+1))==n|m<0;);for(;l-->0;)W*=S[l]==42?M[l]:1;C.WriteLine(W>0);}}

```

Less golfed code:

```
using C=System.Console;

class P
{
    static void Main()
    {
        var S=C.In.ReadToEnd().Replace("\r",""); // read the grid, remove pesky carriage returns
        int W=S.IndexOf('\n')+1,l=S.Length,i=l,d,m,n; // find "width"
        var M=new int[l]; // defaults to 0s

        for(char c;i-->0;) // for each cell

            for(d="^<v>".IndexOf(c=S[m=i]); // find initial direction, if any
                c>14&d>-1; // loop only if we have direction
                d=(m+=d==2?W:d>0?d-2:-W) // move (after iteration)
                >=0&m<l&&"@^<v>".IndexOf(c=S[m])<0?d:-1) // terminate if we hit something or go off edge

                for(d=c==47?3-d:c==92?d^1:d, // mirrors
                    M[n=m]=1; // we have seen this spot
                    c%49<9&&(m=S.IndexOf(c,m+1))==n|m<0;); // portals

        for(;l-->0;) // for each cell
            W*=S[l]==42?M[l]:1; // if *, then mul by whether seen

        C.WriteLine(W>0);
    }
}

```

The new portal handling code utilizes the fact that the String.IndexOf function happily returns -1 (i.e. char not found) if you ask it start looking 1 character beyond the string (throws an exception if you ask it to start any further beyond). This was news to me, but was awfully convenient in this instance.
> 5 votes

---
Tags: code-golf
---


title: Help Me Play My Harmonica

text:
# Question
Title: Help Me Play My Harmonica
Yesterday, I bought a harmonica:

*Figure 1: The harmonica.*

However, my dreams of being able to play soulful blues harmonica that moves people and causes a grown man to cry were quickly dashed by two problems:

1. The harmonica can only play certain notes;
2. I am depressingly bad at playing the harmonica.

Despite my lack of skill at the harmonica, there are still some songs that I can play on it. However, it is not immediately obvious if I am able to play some piece of music on the harmonica or not. Given the notes of a piece of music, write a program to determine if I could play it on my harmonica or not.

As the above picture shows, my harmonica has ten holes in it. With each hole, I can either exhale into it or inhale into it -- the hole that I choose, and whether I inhale or exhale into it changes the pitch of the resulting sound. Each hole has a different pitch on exhaling and inhaling, but there are some combinations that result in the same note. Overall, my harmonica can play 19 unique different pitches. The pitches are presented in musical scientific notation - the letter represents the note, and the number represents which octave it is in.

```
 Hole   Breathing   Note
 1      Exhale      C4
 1      Inhale      D4
 2      Exhale      E4
 2      Inhale      G4
 3      Exhale      G4
 3      Inhale      B4
 4      Exhale      C5
 4      Inhale      D5
 5      Exhale      E5
 5      Inhale      F5
 6      Exhale      G5
 6      Inhale      A5
 7      Exhale      C6
 7      Inhale      B5
 8      Exhale      E6
 8      Inhale      D6
 9      Exhale      G6
 9      Inhale      F6
 10     Exhale      C7
 10     Inhale      A6

```

For example, if I exhaled on hole 3, I'd get a `G4` note. If I inhaled on hole 2, I'd *also* get a `G4` note. If I exhaled on hole 7, I'd get a `C6`.

When I breathe into the harmonica, apart from exhaling or inhaling, I can also choose whether to breathe *thinly* or *widely*. Breathing thinly causes only one hole to sound, whereas breathing widely causes one hole and both holes on either side of that hole to sound. I do not have the embouchure skills to blow onto two holes - it is either one or three.

For instance, if I thinly exhaled onto hole 4, only hole 4 would sound, so I would get a C5 sound. If I widely exhaled onto hole 4, holes 3, 4, and 5 would sound, and I'd get a G4,C5,E5 chord. If I widely inhaled onto hole 4, holes 3, 4, and 5 would sound but they would play the inhale pitches instead, which results in a B4,D5,F5 chord. Note that for the holes on either end, if I breath widely into them only two holes would sound (because there is no hole 0 or hole 11).

However, I cannot inhale and exhale at the same time. For instance, I could exhale into holes 4, 5, and 6 to result in the notes C5, E5, and G5 sounding at the same time, forming a chord. However, I can't inhale and exhale at the same time, so it would be impossible for me to play the chord C5,F5,A5 as I'd have to somehow exhale in hole 4 and inhale in hole 5 and 6. If this is stil unclear, this comment thread might be useful.

The input is the notes of the music. The notes are notated in the same way they are above in the table, and they are comma separated. Notes wrapped in curly brackets represent a chord. For instance:

```
C4,D4,G4,{D5,F5,A5},B5

```

This means, "C4, then D4, then G4, then D5, F5, and A5 at the same time, then B5." Your program will take a string in this format as input and output `True` if it is possible for me to play the music on my harmonica, or `False` otherwise. For sample inputs and outputs, the example above should output `True`. The input `{C5,F5,A5}` on the other hand will output `False`.

This is code golf, so the shortest entry wins.

Here are some test cases:

Input (A C Major scale):

```
C4,D4,E4,F4,G4,A4,B4,C5

```

Output:

```
False

```

(because the harmonica cannot play F4 or A4)

Input (the opening 2 bars of Let It Go):

```
E6,F6,A5,E6,F6,F6,E6,A5,F6,E6

```

Output:

```
True

```

Input:

```
{E6,G6,F6}

```

Output:

```
False

```

Input:

```
{G4,C5,E5},{F5,A5,B5}

```

Output:

```
True

```

**You may assume that chords will come in lower to higher pitch order.**

# Answer
> 2 votes
# Python - ~~218~~ ~~209~~ 189 chars

Minimal:

```
def t(s):from re import sub as r;exec('l=bool([x for x in['+r('"{','("',r('}"','")',r(',','","','"'+s+'"')))+']if"".join(x)not in"C4E4G4C5E5G5C6E6G6C7|D4G4B4D5F5A5B5D6F6A6"])');return not l

```

For ease of reading:

```
def t(s):
    from re import sub as r
    exec('l=bool([x for x in'
         ' [' + r( '"{' , '("' ,
                  r( '}"' , '")' ,
                    r( ',' , '","' , '"' + s + '"' ))) +
         ']'
         ' if "".join(x) not in "C4E4G4C5E5G5C6E6G6C7|D4G4B4D5F5A5B5D6F6A6"])')
    return not l

```

Given a string formated as in the problem description, `t` return `True` if the sequence is playable on the described harmonica, and `False` if it isn't.

There is no check for the order of the notes in the chords. Unless told otherwise, I believe this is sufficient since that isn't in the problem statement, and it passes all given tests in:

```
assert not t("C4,D4,E4,F4,G4,A4,B4,C5")
assert t("E6,F6,A5,E6,F6,F6,E6,A5,F6,E6")
assert not t("{E6,G6,F6}")
assert t("{G4,C5,E5},{F5,A5,B5}")

```

# Answer
> 1 votes
# Javascript - ~~245~~ 243 chars

Minified:

```
function p(s){function f(s){s=s.replace(/\W/g,'');l=s.length;return((l-6)*(l-2)?l-4?'':'C4E4 G6C7 D4G4 F6A6':'C4E4G4C5E5G5C6E6G6C7 D4G4B4D5F5A5B5D6F6A6').indexOf(s)<0?0:''}return s.replace(/{.*?}/g,f).split(',').map(f).join('')?'False':'True'}

```

And expanded:

```
function p(s) {
    function f(s) {
        s = s.replace( /\W/g, '' );
        l = s.length;
        return ( (l-6)*(l-2) ? ( (l-4) ? '' : 'C4E4 G6C7 D4G4 F6A6' ) : 'C4E4G4C5E5G5C6E6G6C7 D4G4B4D5F5A5B5D6F6A6' ).
            indexOf( s ) < 0 ? 0 : ''
    }
    return s.replace( /{.*?}/g, f ).split( ',' ).map( f ).join( '' ) ? 'False' : 'True'
}

```

The function `p` accepts a string as input and returns `True` if the note/chord sequence is playable, `False` otherwise. It returns undefined results if the input isn't syntactically valid.

It also boldly assumes that chord notes are entered in order of ascending hole (such as in the example).

The character count can be reduced by 14 if the function is allowed to return logical `true` and `false` rather than their string equivalents.

# Answer
> 1 votes
# JavaScript (ES6), 230

Just a rewritten version of @COTO's answer:

```
f=s=>{s=s.replace(/\W/g,'');l=s.length;return((l-6)*(l-2)?(l-4?'':'C4E4 G6C7 D4G4 F6A6'):'C4E4G4C5E5G5C6E6G6C7 D4G4B4D5F5A5B5D6F6A6').indexOf(s)<0?0:''};p=s=>{return s.replace(/{.*?}/g,f).split(',').map(f).join('')?'False':'True'}

```

Would appreciate any tips on golfing this down further as I am starting to learn ES6! :-)

# Answer
> 1 votes
## JavaScript ES6, ~~211~~ ~~209~~ 190 chars

I know this can be golfed further. I will try to do so in a few hours;

Run this code in Latest Firefox's Web Console, you will get a method named `C` which you can then call like `C("{G4,C5,E5},{F5,A5,B5}")` and it will return `True` or `False` accordingly.

```
C=n=>(s='D4G4D5F5A5B5D6F6A6,C4E4G4C5E5G5C6E6G6C7',n.split(/[,}{]/g).some(a=>a&&!~s.search(a))||(m=n.match(/{[^}]+/g))&&m.some(a=>a.length!=9|!~s.search(a.replace(/{|,/g,"")))?'False':'True')

```

I am assuming a syntactically valid input.

**EDIT**: Simplified the regex and the length check.

# Answer
> 1 votes
# Scala 178

```
print(readLine./:(""){(a,c)=>if("..C4E4G4C5E5G5C6E6G6C7...D4G4B4D5F5A5B5D6F6A6...."sliding(6)flatMap(y=>Seq("{"+y.diff("..")+"}",y take 2))contains a+c)""else a+c diff ","}=="")

```

Ungolfed:

```
print(
  readLine.foldLeft(""){(a,c)=>                             # loop through the input
    if("..C4E4G4C5E5G5C6E6G6C7...D4G4B4D5F5A5B5D6F6A6...."  # from the harmonica
      .sliding(6)                                     # take 6 at a time
      .flatMap(y=>Seq("{"+y.diff("..")+"}",y take 2)) # chords + single notes
      .contains(a+c)) ""                              # clear matches
    else a+c diff ","                                 # drop commas
  }==""                                               # did everything match?
)

```

Note that malformed input is handled badly - any string is accepted, and many malformed strings return true, for example:

```
{C,7.D}.C

```

prints true.

# Answer
> 1 votes
# Rebol - 188

```
t: func[s][trim/with s ","h: next split n:"C4E4G4C5E5G5C6E6G6C7..D4G4B4D5F5A5B5D6F6A6"2 forskip h 2[i

```

Ungolfed:

```
t: func [s] [
    trim/with s ","
    h: next split n: "C4E4G4C5E5G5C6E6G6C7..D4G4B4D5F5A5B5D6F6A6" 2
    forskip h 2 [insert h '|]
    h: head h

    parse s [
        any [
            h | "{" x: copy c to "}" (unless find n c [c: n])
            :x c "}"
        ]
    ]
]

```

Example usage (in Rebol console):

```
>> t "C4,D4,G4,{D5,F5,A5},B5"
== true

>> t "{C5,F5,A5}"
== false

>> t "C4,D4,E4,F4,G4,A4,B4,C5"
== false

>> t "E6,F6,A5,E6,F6,F6,E6,A5,F6,E6"
== true

>> t "{E6,G6,F6}"
== false

>> t "{G4,C5,E5},{F5,A5,B5}"
== true

```

While this code will catch gibberish like this:

```
>> t "{C,7.D}.C"
== false

```

However it will allow things like this through:

```
>> t "C,4,D4"
== true

```

Because its parsing it as "C4,D4".

Here's a more stricter version of the code:

```
t: func [s] [
    h: next split n: "C4E4G4C5E5G5C6E6G6C7..D4G4B4D5F5A5B5D6F6A6" 2
    forskip h 2 [insert h '|]
    h: head h
    d: ["," | end]

    parse s [
      any [
            [
                h | "{" x: copy c to "}" (
                    unless all [
                        parse c [any [h d]]
                        find n trim/with copy c ","
                    ] [c: n]
                )
                :x c "}"
            ]
            d
      ]
    ]
]

```

This golfs down to 228 chars and now returns `false` on...

```
>> t "C,4,D4"
== false

```

---
Tags: code-golf, music
---


# Question
Title: Catenary Between Two Points (Hanging Chain)
*This is one of several challenges left for the community by Calvin's Hobbies.*

The curve that an idealised hanging rope or chain makes is a catenary.

Image by Bin im Garten, via Wikimedia Commons. Used under the CC-By-SA 3.0 licence.

Write a program that will draw a catenary, as an image, in quadrant 1 of the plane given two points *(x1,y1)*, *(x2,y2)*, and the "rope length" *L*. *L* will be greater than the distance between the two points.

You must also draw axes on the left and bottom sides of the image (400x400 px min) for scale. Only draw the quadrant from x and y in range 0 to 100. (You may assume the points are in range.)

Dots, or something similiar, should be drawn at the *(x1,y1)*, *(x2,y2)* endpoints to distinguish them. **The curve should only be drawn in the space between these points.**

# Answer
# Python + NumPy + Matplotlib, 1131

Just to get us started, here's an attempt that uses no knowledge of calculus or physics other than the fact that the catenary minimizes the energy of a chain. Hey, my algorithm may not be efficient, but at least it's not implemented efficiently either!

```
import math
import random
import numpy as np
import matplotlib.pyplot as plt
length, x0, y0, x1, y1 = input(), input(), input(), input(), input()
chain = np.array([[x0] + [length / 1000.]*1000, [y0] + [0.] * 1000])
def rotate(angle, x, y):
 return x * math.cos(angle) + y * math.sin(angle), -x * math.sin(angle) + y  * math.cos(angle)
def eval(chain, x1, y1):
 mysum = chain.cumsum(1)
 springpotential = 1000 * ((mysum[0][-1] - x1) ** 2 + (mysum[1][-1] - y1)  ** 2)
 potential = mysum.cumsum(1)[1][-1]
 return springpotential + potential
def jiggle(chain, x1, y1):
 for _ in xrange(100000):
  pre = eval(chain, x1, y1)
  angle = random.random() * 2 * math.pi
  index = random.randint(1,1000)
  chain[0][index], chain[1][index] = rotate(angle, chain[0][index], chain[1][index])
  if( pre < eval(chain, x1, y1)):
   chain[0][index], chain[1][index] = rotate(-angle, chain[0][index], chain[1][index])
jiggle(chain, x1, y1)
sum = chain.cumsum(1)
x1 = 2 * x1 - sum[0][-1]
y1 = 2 * y1 - sum[1][-1]
jiggle(chain, x1, y1)
sum = chain.cumsum(1)
plt.plot(sum[0][1:], sum[1][1:])
plt.show()

```
> 5 votes

# Answer
# BBC Basic, 300 ASCII characters, tokenised filesize 260

```
  INPUTr,s,u,v,l:r*=8s*=8u*=8v*=8l*=8z=0REPEATz+=1E-3UNTILFNs(z)/z>=SQR(l^2-(v-s)^2)/(u-r)a=(u-r)/2/z
  p=(r+u-a*LN((l+v-s)/(l-v+s)))/2q=(v+s-l*FNc(z)/FNs(z))/2MOVE800,0DRAW0,0DRAW0,800CIRCLEu,v,8CIRCLEr,s,8FORx=r TOu
    DRAW x,a*FNc((x-p)/a)+q
  NEXT
  DEFFNs(t)=(EXP(t)-EXP(-t))/2
  DEFFNc(t)=(EXP(t)+EXP(-t))/2

```

Emulator at http://www.bbcbasic.co.uk/bbcwin/bbcwin.html

This has obviously been solved before, so the first thing I did was look what others have done.

The equation of a catenary centred at the origin is simply `y=a*cosh(x/a)`. It becomes slightly more complicated if it is not centred at the origin.

Various sources say that if the length and endpoints are known the value for `a` must be determined numerically. There is an unspecified parameter `h` in the wikipedia article. So I found another site and basically followed the method here: http://www.math.niu.edu/~rusin/known-math/99\_incoming/catenary

BBC Basic does not have `sinh` and `cosh` built in, so I defined two functions at the end of the program to calculate them using `EXP`

coordinates for lefthand point must be supplied before righthand point, OP confirmed this is OK. Length is given last. Values can be separated by commas or newlines.

**Ungolfed code**

```
  INPUT r,s,u,v,l

  REM convert input in range 0-100 to graphic coordinates in range 0-800
  r*=8 s*=8 u*=8 v*=8 l*=8

  REM solve for z numerically
  z=0
  REPEAT
    z+=1E-3
  UNTIL FNs(z)/z>=SQR(l^2-(v-s)^2)/(u-r)

  REM calculate the curve parameters
  a=(u-r)/2/z
  p=(r+u-a*LN((l+v-s)/(l-v+s)))/2
  q=(v+s-l*FNc(z)/FNs(z))/2

  REM draw axes, 800 graphics units long = 400 pixels long (2 graphics units per pixel)
  MOVE 800,0
  DRAW 0,0
  DRAW 0,800

  REM draw markers at end and beginning of curve (beginning last, so that cursor is in right place for next step)
  CIRCLE u,v,8
  CIRCLE r,s,8

  REM draw curve from beginning to end
  FORx=r TOu
    DRAW x,a*FNc((x-p)/a)+q
  NEXT

  REM definitions of sinh and cosh
  DEF FNs(t)=(EXP(t)-EXP(-t))/2
  DEF FNc(t)=(EXP(t)+EXP(-t))/2

```
> 3 votes

# Answer
# Python 2.7 + matplotlib, 424

Run as

```
python thisscript.py [length] [x0] [y0] [x1] [y1]

```

If I can assume that x0 is always smaller than x1 character count reduces to **398**

```
from numpy import *
from pylab import *
from scipy.optimize import *
import sys
c=cosh
l,p,q,u,w=map(float,sys.argv[1:])
if p>u:
 p,q,u,w=u,w,p,q
h=u-p
v=w-q
a=brentq(lambda a:(2.*h/a*sinh(0.5*a))**2-l**2-v**2,1e-20,600)
b=brentq(lambda b:c(a*(1.-b))-c(a*b)-a*v/h,-600/a,600/a)
r=linspace(p,u,100)
plot([p,u],[q,w],'ro')
plot(r,h/a*c(((r-p)/h-b)*a)-h/a*c(a*b)+q,'k-')
gca().set_xlim((0,100))
gca().set_ylim((0,100))
show()

```

The magic number 600 you see appearing in some places is due to the fact that cosh(x) and sinh(x) start overflowing around x=710 (so 600 to keep some margin)

> Basically I solve the problem in the frame where the catenary goes trough (0,0) and (x1-x0,(y1-y0)/(x1-x0)) and then remap to the original frame. This improves the numerical stability **a lot**.
> 2 votes

---
Tags: code-golf, graphical-output
---