Two lasers between two mirrors

72

10

What if we have a corridor comprised of two parallel mirrors?

|          |
|          |
|          |
|          |
|          |
|          |
|          |
|          |
|          |
|          |

Now, we shine a laser down it...

|  \       |
|   \      |
|    \     |
|     \    |
|      \   |
|       \  |
|        \ |
|         \|
|         /|
|        / |

Oh, look. It bounced, towards the end, there.

What if we draw two lasers BUT going in the opposite direction?

|  \    /  |
|   \  /   |
|    \/    |
|    /\    |
|   /  \   |
|  /    \  |
| /      \ |
|/        \|
|\        /|
| \      / |

Hmm, they didn't seem to meet, there. That's convenient. What happens if both lasers take up the same space?

|  \     / |
|   \   /  |
|    \ /   |
|     X    |
|    / \   |
|   /   \  |
|  /     \ |
| /       \|
|/        /|
|\       / |

I guess that was pretty obvious, huh?


Drawing these diagrams by hand is pretty laborious (trust me on this). Perhaps some code could do it for us?

  • Write some code to output two parallel mirrors, with two bouncing, intersecting lasers.
  • Input (all integers):
    • The width of the corridor
    • The length of the corridor
    • Starting position of the right-going laser (zero-indexed, must be less than width)
    • Starting position of the left-going laser (zero-indexed, must be less than width)
  • Process
    • If a laser is right going, it will be drawn one space to the right on the following line.
    • If a laser is left going, it will be drawn one space to the left on the following line.
    • If a laser can not take it's sideways step, it will change it's direction, but not it's position.
    • If both laser are at the same index, print an upper-case X at that index.
  • Output
    • A string with multiple lines
    • Each line starts and ends with a pipe character (|)
    • Right-going laser are denoted by a back slash (\)
    • Left-going laser are denoted by a forward slash (/)
    • The intersection of two lasers is denoted by an upper-case X.
  • Any language
  • I'd like to see TIO links
  • Attempt to fix it in the smallest number of bytes

Test cases

width: 6 length: 10 right-going: 1 left-going: 4

| \  / |
|  \/  |
|  /\  |
| /  \ |
|/    \|
|\    /|
| \  / |
|  \/  |
|  /\  |
| /  \ |

width: 6 length: 10 right-going: 0 left-going: 1

|\/    |
|/\    |
|\ \   |
| \ \  |
|  \ \ |
|   \ \|
|    \/|
|    /\|
|   / /|
|  / / |

width: 4 length: 10 right-going: 2 left-going: 0

|/ \ |
|\  \|
| \ /|
|  X |
| / \|
|/  /|
|\ / |
| X  |
|/ \ |
|\  \|

width: 20 length: 5 right-going: 5 left-going: 15

|     \         /    |
|      \       /     |
|       \     /      |
|        \   /       |
|         \ /        |

width: 5 length: 6 right-going: 2 left-going: 2

|  X  |
| / \ |
|/   \|
|\   /|
| \ / |
|  X  |

width: 1 length: 2 right-going: 0 left-going: 0

|X|
|X|

AJFaraday

Posted 2018-04-09T13:28:59.500

Reputation: 10 466

6Suggested edge case: width: 1, length: whatever, right: 0, left: 0 – Arnauld – 2018-04-09T14:58:25.610

2@Arnauld |X| ;) – AJFaraday – 2018-04-09T14:59:25.903

Answers

12

Stax, 40 bytes

àù@○⌡┼PY¼îαφu^·A☺°É⌠■╟¡Åt^◘v(µ╩Ñ♣t{╓○xß╦

Run and debug it

Try it online!

Pretty sure this can be further golfed.

Input is given in the form of width [right-going left-going] length(per comment by @EngineerToast).

ASCII equivalent:

xHXdmzx);hi+x%Y92&;Hi-x%cy=41*47+&2ME:R\{|+m'||S

Weijun Zhou

Posted 2018-04-09T13:28:59.500

Reputation: 3 396

1Might want to note the input format as width [right-going left-going] length – Engineer Toast – 2018-04-10T17:56:08.943

18

JavaScript (ES6), 149 bytes

Takes input in currying syntax (w)(h)([a,b]).

w=>h=>g=(p,d=[1,-1],s=Array(w).fill` `)=>h--?`|${p=p.map((x,i)=>~(k=d[i],s[x]='/X\\'[x-p[i^1]?k+1:1],x+=k)&&x<w?x:x+(d[i]=-k)),s.join``}|
`+g(p,d):''

Try it online!

Commented

w => h =>                  // w = width, h = height
  g = (                    // g = recursive function taking:
    p,                     //   p[] = array holding the point coordinates
    d = [1, -1],           //   d[] = directions
    s = Array(w).fill` `   //   s = array of w spaces (we can't use a string because it's
  ) =>                     //       immutable in JS)
    h-- ?                  // if we haven't reached the last row yet:
      `|${                 //   append the left pipe
      p = p.map((x, i) =>  //   for each x at position i in p[]:
        ~(k = d[i],        //     k = direction for this point
          s[x] = '/X\\'[   //     insert either '/', 'X' or '\' at position x in s
            x - p[i ^ 1] ? //     if p[0] != p[1]:
              k + 1        //       use the direction
            :              //     else:
              1            //       force 'X'
          ], x += k        //     add k to x
        ) &&               //     if the result is not equal to -1
        x < w ?            //     and is less than w:
          x                //       use the current value of x
        :                  //     else:
          x + (d[i] = -k)  //       change the direction and restore the initial value of x
      ),                   //   end of map()
      s.join``}|\n` +      //   join and append s; append the right bar and a linefeed
      g(p, d)              //   followed by the result of a recursive call
    :                      // else:
      ''                   //   stop recursion

Arnauld

Posted 2018-04-09T13:28:59.500

Reputation: 111 334

11

Python 2, 119 bytes

w,l,a,b=input()
exec"print'|%s|'%''.join(' \/X'[sum(i==k%(2*w)for k in[a,~b]+[~a,b]*2)]for i in range(w));a+=1;b-=1;"*l

Try it online!

xnor

Posted 2018-04-09T13:28:59.500

Reputation: 115 687

Can you not golf \\/ to \/? Even though the backslash is interpreted twice, it will still not escape the slash. – Jonathan Frech – 2018-04-10T00:10:15.307

@JonathanFrech You're right, I thought being in a string-in-string would fail, but it indeed doesn't escape either time. – xnor – 2018-04-10T01:15:32.830

Oh jeez, my solution got painfully close to this idea -- working modulo 2w makes a lot of sense in retrospect. Very clever! – Lynn – 2018-04-10T15:02:06.030

9

Python 2, 187 181 179 177 174 172 171 bytes

def f(w,l,a,b,A=1,B=-1):
 while l:l-=1;print'|%s|'%''.join(' \X/'[[0,A,B,2][(i==a)+2*(i==b)]]for i in range(w));a,A=[a,a+A,-A,A][-1<a+A<w::2];b,B=[b,b+B,-B,B][-1<b+B<w::2]

Try it online!


Recursive:

Python 2, 172 bytes

def f(w,l,a,b,A=1,B=-1):
 if not-1<a<w:A=-A;a+=A
 if not-1<b<w:B=-B;b+=B
 if l:print'|%s|'%''.join(' \X/'[[0,A,B,2][(i==a)+2*(i==b)]]for i in range(w));f(w,l-1,a+A,b+B,A,B)

Try it online!


Recursive, alternative print:

Python 2, 172 bytes

def f(w,l,a,b,A=1,B=-1):
 if not-1<a<w:A=-A;a+=A
 if not-1<b<w:B=-B;b+=B
 if l:L=[' ']*w;L[a]=' \/'[A];L[b]=[' \/'[B],'X'][a==b];print'|%s|'%''.join(L);f(w,l-1,a+A,b+B,A,B)

Try it online!

TFeld

Posted 2018-04-09T13:28:59.500

Reputation: 19 246

I am once again amazed by the speed of first answers on code golf challenges. Nice one! :) – AJFaraday – 2018-04-09T13:45:36.040

9

Python 2, 168 bytes

w,n,r,l=input()
R=L=1
exec"""
d=[~r*R,-~l*L].count
print'|%s|'%''.join(' /\X'[2*d(~x)|d(x+1)]for x in range(w))
if-1<r+R<w:r+=R
else:R=-R
if-1<l-L<w:l-=L
else:L=-L"""*n

Try it online!

Lynn

Posted 2018-04-09T13:28:59.500

Reputation: 55 648

8

C (clang), 240 236 208 bytes

#define g(a,b) b?a++,a==x&&(a=x-1,b=0):a--,a==-1&&(a=0,b=1)
i,m,n,o,p,t[]={47,92};f(x,y,r,l){for(m=1,n=0;y--;puts("|"),g(r,m),g(l,n))for(printf("|"),i=0;i<x;o=i==r,p=i++==l,putchar(o*p?88:o?t[m]:p?t[n]:32));}

Try it online!

f() takes parameters as follows:

x = width,
y = length,
r = Initially right-going line starting position
l = Initially left-going-line starting position

-4 Bytes. credits Kevin Cruijssen. Thanks

GPS

Posted 2018-04-09T13:28:59.500

Reputation: 341

1

You can golf 3 bytes by changing the while to a for to remove the {} and one of the semi-colons. And 1 more byte by changing c&&d to c&d. Try it online 236 bytes.

– Kevin Cruijssen – 2018-04-10T07:48:16.417

Looks like you are taking two extra inputs, that is not allowed afaik. – O.O.Balance – 2018-04-10T08:25:22.840

@O.O.Balance Taking two extra inputs allows me to handle input conditions that original question didn't accounted for, i.e. lines starting in same direction. But if you can point me to a general-consensus vote that says this is disallowed, I'll be happy to remove variables from parameter and add to globals. – GPS – 2018-04-10T08:48:28.460

1

You're not supposed to solve a generalisation of the challenge, but the challenge as specified. Regarding extra inputs, I dug around meta a bit and found this: https://codegolf.meta.stackexchange.com/a/12696/79343 I'm thinking it must be written up somewhere else, too, but i can't find it atm. It is however the norm.

– O.O.Balance – 2018-04-10T09:08:29.777

@O.O.Balance I didn't think that was the norm, but I understand objection to passing special values as parameters. I could've initiaized those params in my function with 6 bytes penalty, but I improved the answer instead. Thanks for your inputs :) – GPS – 2018-04-10T13:00:26.227

1In your g macro, you can golf 2 bytes by changing a==-1 to a<0. – JohnWells – 2018-07-08T21:55:39.430

1Actually got more in the macro, a++,a and a--,a can golf 2 bytes each to ++a and --a – JohnWells – 2018-07-08T22:35:54.390

I checked; works on GCC too. – SIGSTACKFAULT – 2018-07-09T17:09:46.253

187 bytes – ceilingcat – 2019-10-12T03:05:31.017

7

Canvas, 66 40 bytes

{²Xø⁶╵[⁷/²2%[↔}∔};x╷?⁷∔⁷+╷}[j}}n⁶[|PJp|p

Try it here!

dzaima

Posted 2018-04-09T13:28:59.500

Reputation: 19 048

5

Charcoal, 56 50 bytes

↷PIθM⊕η→IθF²«J⊕⎇ιεζ⁰FIθ«✳§⟦↘↙⟧ι∨⁼KKψX¿⁼KK|«¿ι→←≦¬ι

Try it online! Link is to verbose version of code. Edit: Saved 6 bytes by reducing reliance on pivoting. Explanation:

↷PIθM⊕η→Iθ

Print the sides.

F²«

Loop over the two lasers.

J⊕⎇ιεζ⁰

Move to the start of the laser.

FIθ«

Loop over the height.

✳§⟦↘↙⟧ι∨⁼KKψX

Draw a \ or / in the appropriate direction, unless the square is not empty, in which case draw an X.

¿⁼KK|«

Have we hit a side?

¿ι→←≦¬ι

If so then take one step sideways and invert the direction of travel.

Neil

Posted 2018-04-09T13:28:59.500

Reputation: 95 035

This goes out of bounds when the input is "10 2 4 2" – Martijn Vissers – 2018-04-12T14:56:02.153

1@MartijnVissers Well yes, if your width is 2, then your positions can only be 0 or 1... – Neil – 2018-04-12T15:54:16.700

5

Java (JDK 10), 186 bytes

(w,h,r,l)->{var x="";for(int i=0,j,R=1,L=-1;i++<h;l+=L,l+=l<0|l>=w?L=-L:0,r+=R,r+=r<0|r>=w?R=-R:0,x+="|\n")for(j=0,x+="|";j<w;j++)x+="/X\\ ".charAt(j==r?j==l?1:R+1:j==l?L+1:3);return x;}

Try it online!

Olivier Grégoire

Posted 2018-04-09T13:28:59.500

Reputation: 10 647

3

PHP, 177 169 166 bytes

[,$w,$h,$a,$b]=$argv;for($e=-$d=1;$h--;$s[$a+=$d]^L?:$a+=$d=-$d,$s[$b+=$e]^L?:$b+=$e=-$e){$s=str_pad("",$w)."|";$s[$b]="X\/"[$e];$s[$a]="X\/"[$a-$b?$d:0];echo"|$s
";}

requires PHP 7.1 for negative string indexes, PHP 5.5 or later for indexing string literals.
for PHP <7.1, remove ^L, replace "X\/" with "/X\\", :0 with +1:1, [$e] with [$e+1], remove ."|" and insert | before the newline. (+3 bytes)
for PHP < 5.5, replace "/X\\" with $p and insert $p="/X\\"; at the beginning. (+2 bytes)

takes input from command line arguments. Run with -nr or try them online.

Titus

Posted 2018-04-09T13:28:59.500

Reputation: 13 814

It's unfortunate that onlinephpfunctions.com does not save the correct PHP version in the sharing link... – Arnauld – 2018-04-10T12:03:51.003

3

Python 3, 162 bytes

from numpy import*
def f(w,h,u,v):
 v=w+w-v-1;T=eye(w);M=vstack([T,2*T[::-1]]*2*h)
 for r in M[u:u+h,:]+M[v:v+h,:]:print('|%s|'%''.join(' \/X'[int(i)]for i in r))

Try it online!

RootTwo

Posted 2018-04-09T13:28:59.500

Reputation: 1 749

I like the formatting in your test suite, reliably showing the inputs against the output... Nice one ;) – AJFaraday – 2018-04-11T08:55:06.800

3

Ruby, 117 bytes

->w,h,a{a[1]-=w;(1..h).map{s=' '*w;a.map!{|x|d=x<0?-1:1;s[x]='X\\/'[s[x][/ /]?d:0];x+=d;x==w ?-1:x<-w ?0:x};?|+s+?|}}

Try it online!

Anonymous lambda taking input as width w, height h and an array of starting points a.

Kirill L.

Posted 2018-04-09T13:28:59.500

Reputation: 6 693

You kind of made my day by making it an expandable array, not just 2 starting points. – AJFaraday – 2018-04-11T12:57:34.713

2

PowerShell, 243 233 222 205 bytes

param($w,$h,$a,$b)$l,$r,$s=1,-1,' \/'
1..$h|%{$p,$p[$b],$p[$a]=[char[]](' '*$w),$s[$r],($s[$l],"x")[!($a-$b)]
if($a+$l-in($z=0..($w-1))){$a+=$l}else{$l*=-1}if($b+$r-in$z){$b+=$r}else{$r*=-1}"|$(-join$p)|"}

Try it online!

Oooof. those logic blocks are big and dirty and mostly duplicated. The next step would be rewriting them so they don't need the else statement.

Veskah

Posted 2018-04-09T13:28:59.500

Reputation: 3 580

1

Python 2, 165 164 bytes

w,h,x,y=input()
a,b,s=1,-1,' \/'
exec"""l=[' ']*w
l[x],l[y]=s[a],s[b]if x-y else'X'
if-1<x+a<w:x+=a
else:a=-a
if-1<y+b<w:y+=b
else:b=-b
print'|%s|'%''.join(l)
"""*h

Saved a byte thanks to Jonathan Frech.
Try it online!

user48543

Posted 2018-04-09T13:28:59.500

Reputation:

1\\/ is equivalent to \/. – Jonathan Frech – 2018-04-10T00:07:50.583

1

K (ngn/k), 58 bytes

{" \\/X|"4,'(+/3!1 2*(x#'e+2*|e:=2*x)(2*x)!z+(!y;-!y)),'4}

Try it online!

anonymous function that accepts three arguments: x the width, y the length, z a pair of starting positions for the lasers

ngn

Posted 2018-04-09T13:28:59.500

Reputation: 11 449

1

C (gcc), 169 bytes

A,B,c;f(w,l,a,b){for(A=1,B=-1;l--;a+=A,a<0|a==w?A=-A,a+=A:0,b+=B,b<0|b==w?B=-B,b+=B:0,puts("|"))for(c=-1;c<w;c++)putchar(c<0?'|':a^c?b^c?32:B>0?92:47:b^c?A>0?92:47:88);}

Try it online!

gastropner

Posted 2018-04-09T13:28:59.500

Reputation: 3 264

163 bytes – ceilingcat – 2018-11-27T01:35:21.347

1

Kotlin, 322 311 302 bytes

Changed how I put laser direction in string for 11 bytes. Moved assignment out of when for 9 bytes.

{w:Int,h:Int,r:Int,l:Int->{var a=""
var f=r
var d=1>0
var s=l
var t=!d
for(o in 1..h){a+="|"
for(c in 0..w-1)a+=when{c==f&&c==s->"X"
c==f&&d||c==s&&t->"\\"
c==f||c==s->"/"
else->" "}
a+="|\n"
if(d){if(++f==w){--f
d=!d}}else if(--f<0){f=0
d=!d}
if(t){if(++s==w){--s
t=!t}}else if(--s<0){s=0
t=!t}}
a}()}

Try it online!

JohnWells

Posted 2018-04-09T13:28:59.500

Reputation: 611