Lucas Vs. The Garage Door Remote

Disclaimer

While I know there is this particular related question, my question uses two garage doors, a randomizing component, and I'm also basing this on real life events, seeing my son accidentally lowered one of said garage doors whilst I was walking out of the garage last week... Nothing like a blow to the head to get the creative juices flowing! ;)

The Background

Lucas (my 15 month old son) likes to play with the garage remote. There are two buttons on this remote, one for the left garage door, and one for the right garage door. Both buttons work in the same manner; press once to get the door to start opening, press again to stop, press again to start closing, press again to stop again, and so on.

Lucas loves this remote, he'll randomly press one of the buttons, or both, or none at all. If both are pressed, no signal is sent, but a press of one button will send out a signal.

So, the code-golf challenge is divided on two parts:

Part One

Generate a 60 character long string representing Lucas random button presses over a minute. "Random" in this case means "with an equal chance of each input at each tick". The characters are as follows:

• 0: Lucas has either pressed no button, or has pressed both buttons. Either way, no signal has been sent.
• 1: The button for the left garage door has been pressed by Lucas
• 2: The button for the right garage door has been pressed by Lucas

Part Two

Using the string generated in Part One, simulate the opening and closing of the two-car garage using the numbers as triggers for opening, stopping and closing these doors.

My garage doors are pretty quick (see Disclaimer above as to why). Once you press the button it takes four seconds to be fully open or closed.

So, if closed:

• 0 sec: 0% open (closed); when button is pressed, door starts opening
• 1 sec: 25% open
• 2 sec: 50% open
• 3 sec: 75% open
• 4 sec: 100% open, door stops

And therefore, if open:

• 0 sec: 100% open; when button is pressed, door starts closing
• 1 sec: 75% open
• 2 sec: 50% open
• 3 sec: 25% open
• 4 sec: 0% open (closed), door stops

If a particular door is in motion, a signal to that same door will stop it. The next signal sent to that same door after that will send it moving in the opposite direction. If a door is stopped when it has previously been in motion and is now fully open or fully closed when the "stop" signal is received, the door will register as "stopped" in the fully-open or fully-closed state, ready to move in the opposite direction when it receives a new signal.

With this simulation, both garage doors will be initially in the closed position. So, let's look at a 10 second list of commands and see what happens if Lucas was to perform them on the remote:

2120221120
2: (L:0% stopped, R:0% opening)
1: (L:0% opening, R:25% opening)
2: (L:25% opening, R:50% stopped)
0: (L:50% opening, R:50% stopped)
2: (L:75% opening, R:50% closing)
2: (L:100% stopped, R:25% stopped)
1: (L:100% closing, R:25% stopped)
1: (L:75% stopped, R:25% stopped)
2: (L:75% stopped, R:25% opening)
0: (L:75% stopped, R:50% opening)


Output

The first part of the output requires the display of the 60 character long string of random "0", "1" and "2" characters generated from Part One. eg. 212022112021202211202120221120212022112021202211202120221120

Below this string, is the processing of these "signals" according to the rules mentioned above of how the garage doors will behave with each respective character (on a second by second basis). You should end up with 60 lines as a result below the initial display string.

Each of these processed lines will be in the form of: N: (L:X% XXXXXXX, R:Y% YYYYYYY) where:

• N is the nth character from the respective random string, which will be in the form of a 0, 1, or 2.
• X% is the percentage of openness of the left door (there is no zero padding)
• XXXXXXX is the status of the left door. If the door is not in motion (i.e. not opening or closing) the status "stopped" is enforced, meaning it has been stopped in motion (only possible at 25%, 50% or 75%) or stopped when fully open (100%) or fully closed (0%). Otherwise, the door will either be "opening" or "closing".
• Y% is the percentage of openness of the right door (there is no zero padding)
• YYYYYYY is the status of the right door. If the door is not in motion (i.e. not opening or closing) the status "stopped" is enforced, meaning it has been stopped in motion (only possible at 25%, 50% or 75%) or stopped when fully open (100%) or fully closed (0%). Otherwise, the door will either be "opening" or "closing".

Example shown below using 10 "signals" and 10 processed lines

2120221120
2: (L:0% stopped, R:0% opening)
1: (L:0% opening, R:25% opening)
2: (L:25% opening, R:50% stopped)
0: (L:50% opening, R:50% stopped)
2: (L:75% opening, R:50% closing)
2: (L:100% stopped, R:25% stopped)
1: (L:100% closing, R:25% stopped)
1: (L:75% stopped, R:25% stopped)
2: (L:75% stopped, R:25% opening)
0: (L:75% stopped, R:50% opening)


This is code-golf, so the shortest code will be the clear winner. I've made this a little easy by using phrases like "opening", "stopped" and "closing", which are all seven letters... so you may want to work that into your strategy.

Best of luck!

• You should define a clearer output format for Part 2. Commented Aug 28, 2016 at 23:23
• @LegionMammal978 What do you feel is missing from the output? Commented Aug 29, 2016 at 1:12
• I don't at the moment, but I do think it's a neat question--I may tackle it. Commented Aug 29, 2016 at 4:10
• Why isn't the last 1 command stopping the left door at 75% in your example? Commented Aug 29, 2016 at 14:52
• Should 0,1, and 2 all appear equally in the first part, or should no-press, double-press, left-press, and right-press all appear equally? (meaning, 0 is more likely because it represents two scenarios which cause the same and result...) Commented Aug 29, 2016 at 15:56

Javascript (ES6), 277275263253250247 234 bytes

_=>(d=[0,0],l=s='',[...Array(60)].map(_=>(s+=
${c=Math.random()*3|0}:(,l+=c,d=d.map((v,i)=>(v=v&8?v&16?v-27?v+1:20:v-9?v-1:0:v,v^=c+~i?0:v&8||24,s+='LR'[i]+:${(v&7)*25}% +(v&8?v&16?'opening':'closing':'stopped')+',)'[i],v)))),l+s)


Ungolfed and commented

_ => (
// Initialize array:
//   - d = door states as integers
//     - bits 0 to 2: door opening state (from 0b000 = 0% to 0b100 = 100%)
//     - bit #3: door in motion (0: no, 1: yes)
//     - bit #4: door direction (0: closing, 1: opening)
d = [0, 0],

// Initialize strings:
//   - l = list of commands
//   - s = door states in plain text
l = s = '',

// Iterate on an array of 60 entries.
[...Array(60)].map(_ => (
// c = new random command (0, 1 or 2)
// Append new line and new command to s.
s += \n${c = Math.random() * 3 | 0}:(, // Append new command to l. l += c, // For each door ... d = d.map((v, i) => ( // If the door is in motion, update its opening state. // Clear the 'in motion' bit if a bound is reached (either closed or fully open). v = v & 8 ? v & 16 ? v - 27 ? v + 1 : 20 : v - 9 ? v - 1 : 0 : v, // If the current command is intended for this door, update its direction and // 'in motion' bit. Direction is changed on the 'stopped => moving' transition. v ^= c + ~i ? 0 : v & 8 || 24, // Translate the door state in plain text and append it to s s += 'LR'[i] + :${(v & 7) * 25}%  +
(v & 8 ? v & 16 ? 'opening' : 'closing' : 'stopped') +
',)'[i],

// Value to be taken into account by map()
v
))
)),

// Final result to be returned
l + s
)


Demo

let f =
_=>(d=[0,0],l=s='',[...Array(60)].map(_=>(s+=
${c=Math.random()*3|0}:(,l+=c,d=d.map((v,i)=>(v=v&8?v&16?v-27?v+1:20:v-9?v-1:0:v,v^=c+~i?0:v&8||24,s+='LR'[i]+:${(v&7)*25}% +(v&8?v&16?'opening':'closing':'stopped')+',)'[i],v)))),l+s)

console.log(f())

• Wow, I'm impressed with the one liner and throwing it into console.log at that! Well done! Commented Aug 29, 2016 at 21:04
• Curiously not working in Firefox, just 4 lines in output, like this 112200001100122021010101012100000010011200201022122021012211 [ "L:25% stopped", "R:25% stopped" ](newlines after comma and brackets) Commented Aug 29, 2016 at 21:50
• @edc65 - My bad, actually. I misread the instructions about the output format. This is fixed. Commented Aug 29, 2016 at 22:52
• @Arnauld You could also remove the parentheses from v^=(c-i-1?0:v&8||24) to save you two bytes. Commented Aug 30, 2016 at 3:00
• PS @Arnauld, thanks for taking part! Commented Aug 30, 2016 at 4:58

Python 2, 377370361357345335326316312306 304 bytes

The second indent level is a raw tab (\t), which plays really badly with Markdown, so it's been replaced by two spaces.

from random import*
p=[randint(0,2)for d in[[0]*3]*60]
printp[1::3]
v=[-1]*3
c=[0]*3
f=lambda y:str(c[y]*25)+'% '+'csoltpooespnipinengdg'[d[y]+1::3]
for x in p:
for i in 1,2:
q=d[i];c[i]+=q
if(2*-~q==c[i])*q:v[i]=q;d[i]=0
z=d[x]
if z:v[x]=z
d[x]=-v[x]*(z==0);print'%d: (L:%s, R:%s)'%(x,f(1),f(2))


I'm almost certain this can be golfed further.

import random

# Generate the random string - represented as a list of ints
presses = [random.randint(0, 2) for _ in range(60)]
print ''.join(map(str, presses))

# Constants for door states used for easier reading
CLOSING = -1
STOPPED = 0
OPENING = 1

# Variables representing the state of the garage doors
# There's a third element in these so that x[0] resolves to a dummy slot
# (this way, we can avoid a conditional down the road)
prev_states = [CLOSING, CLOSING, 0]
door_states = [STOPPED, STOPPED, 0]
door_pcts = [0, 0, 0]  # delta 1 = 25%

for press in presses:
# Close/open the door 1 more
for i in 1, 2:
if door_states[i] != STOPPED:
delta_pct, stop_pct = (-1, 0) if door_states[i] == CLOSING else (1, 4)
door_pcts[i] += delta_pct
if door_pcts[i] == stop_pct:
prev_states[i] = door_states[i]
door_states[i] = STOPPED

# Handle pressing a button
# If the press is 0 (no press), the 0th element resolves to a dummy
# door, thus saving us an expensive conditional

if door_states[press] == STOPPED:
door_states[press] = -prev_states[press]
else:
prev_states[press] = door_states[press]
door_states[press] = STOPPED

# Print the status update
print '%d: (L:%d%% %s, R:%d%% %s)' % (
press,
door_pcts[0]*25,
['closing', 'stopped', 'opening'][door_states[0]+1],
door_pcts[1]*25,
['closing', 'stopped', 'opening'][door_states[1]+1],
)


Saved 4 14 15 bytes thanks to @TheBikingViking!

Saved 6 bytes thanks to @ValueInk!

• You can change range(60) to [0]*60. Commented Aug 29, 2016 at 20:50
• @TheBikingViking Thanks! I'm editing that in now. Commented Aug 29, 2016 at 20:56
• You can do 'p'[1::3] (replace apostrophes with backticks) instead of ''.join(map(str,p)). Commented Aug 29, 2016 at 21:28
• (4,0)[q<0]==c[i]and q -> ((4,0)[q<0]==c[i])*q Commented Aug 29, 2016 at 21:39
• @ValueInk That line abuses a bug in Python 2's list comprehensions to set n to that string. n is used on the final line to extract closing, stopped, opening from that string. Commented Aug 30, 2016 at 23:22

Pyth, 156149 145 bytes

jkJmO3U60K=G*]Z3=b*3]_1VJFHS2I&=T@KHq*2hT@XHGTH XbHT XKH0)) XKN*_@XbN|@KN@bNN!@KN%+N": (L:%s, R:%s)"m++*@Gd25"% "%3>"csoltpooespnipinengdg"h@KdS2


A direct translation of my Python answer.

Try it online!

Explanation:

jk                              " print ''.join(map(str,                   "
JmO3U60                         "  J = [randint(0,2) for _ in range(60)])) "
K=G*]Z3                         " K = copy(G = [0] * 3)                    "
=b*3]_1                         " b = [-1] * 3                             "
VJ                              " for N in J:                              "
FHS2                            "  for H in range(1, 3):                   "
I&=T@KH                         "   if ((T = K[H]) and                     "
q*2hT@XHGTH                     "       (2 * (T + 1) == (G[H] += T)[H]):   "
XbHT                           "    b[H] = T                              "
XKH0))                         "    K[H] = 0                              "
XKN*_@XbN|@KN@bNN              "  K[N] = (-(b[N] = K[N] or B[N])[N] *     "
!@KN                            "   (not K[N]))                            "
%+N": (L:%s, R:%s)"             "  print(str(N) + ': (L:%s, R:%s)' %       "
m++                             "   map(lambda d:                          "
*@Gd25                          "    G[d] * 25 +                           "
"% "                            "    '% ' +                                "
%3>"csoltpooespnipinengdg"h@Kd  "    'csoltpooespnipinengdg'[K[d]+1::3]]   "
S2                              "   ), range(1, 3))                        "

• Wow! Thanks for this answer, as well as the explanation of the code... I was actually making sense of it by the time I reached the end of it... Commented Sep 1, 2016 at 12:29

Ruby, 263261260 254 bytes

How did JavaScript's answer get so short??? It overtook mine while I was away and still is winning currently...

s=(1..60).map{rand 3}
puts s*''
D=1,2
d=[25]*3;a=[0]*3;m=[p]*3
s.map{|i|D.map{|j|m[j]&&a[j]+=d[j];(0..100)===a[j]+d[j]||i!=j&&(d[j]*=-1;m[j]=p)}
(m[i]^=1)||d[i]*=-1
puts"#{i}: (L%s, R%s)"%D.map{|j|":#{a[j]}% #{%w"stopped opening closing"[m[j]?d[j]:0]}"}}


C, 420433424 374 bytes

#define F(X,x) X=x==1?X+1:x==2?X-1:X;X=X<0?0:X>4?4:X;x=X==0?0:X==4?3:x
#define G(x) x=x==1?3:x==2?0:x==3?2:x+1
#define H(X,x) X*25,x==0||x==3?"stopped":x==1?"opening":"closing"
c,i,l,r,L,R,x[60];main(){while(i<60)printf("%d",x[i++]=random()%3);while(c<60){if(x[c]==1)G(l);else if(x[c]==2)G(r);printf("\n%d: (L:%d%% %s, R:%d%% %s)",x[c++],H(L,l),H(R,r));F(L,l);F(R,r);}}


Doesn't seed the random generator but does use random for a better distribution. There must be a better way to golf this logic though...

110121100121212100112200222111200020111100022122202112202211002
1: (L:0% opening, R:0% stopped)
1: (L:25% stopped, R:0% stopped)
0: (L:25% stopped, R:0% stopped)
1: (L:25% closing, R:0% stopped)
2: (L:0% stopped, R:0% opening)
1: (L:0% opening, R:25% opening)
1: (L:25% stopped, R:50% opening)
0: (L:25% stopped, R:75% opening)
0: (L:25% stopped, R:100% stopped)
1: (L:25% closing, R:100% stopped)
2: (L:0% stopped, R:100% closing)
1: (L:0% opening, R:75% closing)
2: (L:25% opening, R:50% stopped)
1: (L:50% stopped, R:50% stopped)
2: (L:50% stopped, R:50% opening)
1: (L:50% closing, R:75% opening)
0: (L:25% closing, R:100% stopped)
0: (L:0% stopped, R:100% stopped)
1: (L:0% opening, R:100% stopped)
1: (L:25% stopped, R:100% stopped)
2: (L:25% stopped, R:100% closing)
2: (L:25% stopped, R:75% stopped)
0: (L:25% stopped, R:75% stopped)
0: (L:25% stopped, R:75% stopped)
2: (L:25% stopped, R:75% opening)
2: (L:25% stopped, R:100% closing)
2: (L:25% stopped, R:75% stopped)
1: (L:25% closing, R:75% stopped)
1: (L:0% opening, R:75% stopped)
1: (L:25% stopped, R:75% stopped)
2: (L:25% stopped, R:75% opening)
0: (L:25% stopped, R:100% stopped)
0: (L:25% stopped, R:100% stopped)
0: (L:25% stopped, R:100% stopped)
2: (L:25% stopped, R:100% closing)
0: (L:25% stopped, R:75% closing)
1: (L:25% closing, R:50% closing)
1: (L:0% opening, R:25% closing)
1: (L:25% stopped, R:0% stopped)
1: (L:25% closing, R:0% stopped)
0: (L:0% stopped, R:0% stopped)
0: (L:0% stopped, R:0% stopped)
0: (L:0% stopped, R:0% stopped)
2: (L:0% stopped, R:0% opening)
2: (L:0% stopped, R:25% stopped)
1: (L:0% opening, R:25% stopped)
2: (L:25% opening, R:25% closing)
2: (L:50% opening, R:0% opening)
2: (L:75% opening, R:25% stopped)
0: (L:100% stopped, R:25% stopped)
2: (L:100% stopped, R:25% closing)
1: (L:100% closing, R:0% stopped)
1: (L:75% stopped, R:0% stopped)
2: (L:75% stopped, R:0% opening)
2: (L:75% stopped, R:25% stopped)
0: (L:75% stopped, R:25% stopped)
2: (L:75% stopped, R:25% closing)
2: (L:75% stopped, R:0% opening)
1: (L:75% opening, R:25% opening)
1: (L:100% closing, R:50% opening)


Older version 1:

c,i,l,r,L,R,x[60];main(){while(i<60)printf("%d",x[i++]=random()%3);while(c<60){if(x[c]==1)l=l==1?3:l==2?0:l==3?2:l+1;else if(x[c]==2)r=r==1?3:r==2?0:r==3?2:r+1;printf("\n%d: (L:%d%% %s, R:%d%% %s)",x[c++],L*25,l==0||l==3?"stopped":l==1?"opening":"closing",R*25,r==0||r==3?"stopped":r==1?"opening":"closing");L=l==1?L+1:l==2?L-1:L;R=r==1?R+1:r==2?R-1:R;L=L<0?0:L>4?4:L;R=R<0?0:R>4?4:R;l=L==0?0:L==4?3:l;r=R==0?0:R==4?3:r;}}


Older version 2:

c,i,l,r,L,R,x[60];g(){while(i<60)printf("%d",x[i++]=random()%3);}main(){g();while(c<60){if(x[c]==1)l=l==1?3:l==2?0:l==3?2:l+1;else if(x[c]==2)r=r==1?3:r==2?0:r==3?2:r+1;printf("%d: (L:%d%% %s, R:%d%% %s)\n",x[c++],L*25,l==0||l==3?"stopped":l==1?"opening":"closing",R*25,r==0||r==3?"stopped":r==1?"opening":"closing");L=l==1?L+1:l==2?L-1:L;R=r==1?R+1:r==2?R-1:R;L=L<0?0:L>4?4:L;R=R<0?0:R>4?4:R;l=L==0?0:L==4?3:l;r=R==0?0:R==4?3:r;}}

• Can you convert that into code? Commented Sep 1, 2016 at 0:12

PHP, 254247246245235230 226 bytes

beating ES again!

for($t=60;$t--;)$s.=rand()%3;echo$s;for(;++$t<60;print"$c: ($o[1],$o[2])")for($i=3;--$i;$o[$i]='.LR'[$i].':'.$d[$i]*25 .'% '.[opening,stopped,closing][abs($z-1)])if(((1&$z=&$r[$i])&&!(3&$d[$i]+=2-$z))|$i&$c=$s[$t])$z=++$z%4;


golfed down from these 311 (the first complete version, already had some golfing):

<?for($i=60;$i--;)$s.=rand(0,2);echo$s;$d=$r=[0,0];$n=[L,R];$p=[stopped,opening,stopped,closing];for($t=-1;++$t<60;print"
$c: (".join(', ',$x).")")for($m=$c=$s[$t],$i=-1;$i++<1;){if($r[$i]&1)if(!($d[$i]+=2-$r[$i])||4==$d[$i])$m|=$i+1;if($m&$i+1)$r[$i]=(1+$r[$i])%4;$x[$i]="$n[$i]:".($d[$i]*25)."% ".$p[$r[$i]];}  breakdown for($t=60;$t--;)$s.=rand()%3;   // part 1               also initializes $t to -1 echo$s;
for(
;
++$t<60; print"\n$c: ($o[1],$o[2])" // print output
)
for($i=3;--$i;  // loop $i from 2 to 1 (door number) // generate output$o[$i]='.LR'[$i].':'.$d[$i]*25 .'% '
.[opening,stopped,closing][abs($z-1)] // map 0123 to 1012 ) if(((1&$z=&$r[$i])  // if door in motion        ... and reference the array item
&&!(3&              // 2. if end position   "&&" needed for short circuit
$d[$i]+=2-$z // 1. move door 2-$z maps 1,3 to 1,-1 = delta
)
)|$i&$c=$s[$t])     // 3. or if button $i pressed "|" needed for no short circuit$z=++$z%4; // rotate direction ++$z%4 maps 0,1,2,3 to 1,2,3,0
// generate output (loop post condition)
// print output (loop post condition)

• @Arnauld: got you! :) Commented Sep 12, 2016 at 21:22

Java 8 lambda, 500 characters

I did my best, here is what I came up with:

()->{String r="";int i=0,l=0,m=0,n=1,o=1,p=0,q=0;for(;i++<60;)r+=(int)(Math.random()*3);for(char s:r.toCharArray()){l+=p;m+=q;if(l>99&p>0){l=100;p=25*(((n=++n%4)-1)%2);}if(l<1&p<0){l=0;p=25*(((n=++n%4)-1)%2);}if(m>99&q>0){m=100;q=25*(((o=++o%4)-1)%2);}if(m<1&q<0){m=0;q=25*(((o=++o%4)-1)%2);}if(s<49);else if(s>49)q=25*(((o=++o%4)-1)%2);else p=25*(((n=++n%4)-1)%2);r+="\n"+s+": (L:"+l+"% "+(p<0?"closing":p>0?"opening":"stopped")+", R:"+m+"% "+(q<0?"closing":q>0?"opening":"stopped")+")";}return r;}


Ungolfed into a complete class:

public class Q91479 {

public static String movedDoorsCombined() {
String result = "";
int i = 0, leftDoor = 0, rightDoor = 0, stepLeft = 1, stepRight = 1, changeLeft = 0, changeRight = 0;

for (; i++ < 60;) {
result += (int) (Math.random() * 3);
}

for (char step : result.toCharArray()) {
// update stats
leftDoor += changeLeft;
rightDoor += changeRight;

if (leftDoor > 99 & changeLeft > 0) {
leftDoor = 100;
changeLeft = 25 * (((stepLeft = ++stepLeft % 4) - 1) % 2);
}
if (leftDoor < 1 & changeLeft < 0) {
leftDoor = 0;
changeLeft = 25 * (((stepLeft = ++stepLeft % 4) - 1) % 2);
}
if (rightDoor > 99 & changeRight > 0) {
rightDoor = 100;
changeRight = 25 * (((stepRight = ++stepRight % 4) - 1) % 2);
}
if (rightDoor < 1 & changeRight < 0) {
rightDoor = 0;
changeRight = 25 * (((stepRight = ++stepRight % 4) - 1) % 2);
}

if (step < 49) {
// 0
}
else if (step > 49) {
// right
changeRight = 25 * (((stepRight = ++stepRight % 4) - 1) % 2);
}
else {
// left
changeLeft = 25 * (((stepLeft = ++stepLeft % 4) - 1) % 2);
}
result += "\n" + step + ": (L:" + leftDoor + "% "
+ (changeLeft < 0 ? "closing" : changeLeft > 0 ? "opening" : "stopped")
+ ", R:" + rightDoor + "% "
+ (changeRight < 0 ? "closing" : changeRight > 0 ? "opening" : "stopped")
+ ")";
}
return result;
}
}


Pretty straight forward. The stepLeft/stepRight variables circle from 0-3. Doing some simple maths changeLeft/changeRight hold the respective relative changes per step, which will be added to leftDoor/rightDoor. Many if statements for catching when the door has to stop on it's own.

Feel free to help me shorten this, I think there's a lot to do.

Haskell (lambdabot) - 409 bytes

p=(cycle[0,1,0,-1],0)
t(d:q,s)=(if d/=0&&(s+d<1||3<s+d)then q else d:q,s+d)
k i(a,b)=[o i,": (L:",j a,", ","R:",j b,")"]>>=id
j(d:_,s)=o(round$(fromIntegral s/4)*100)++"% "++words"closing stopped opening"!!(d+1) s=scanl$ \(a,b)i->i(t a,t b)
main=do b<-(fmap(round.(*(2::Float))).take 60<$>randoms)<$>getStdGen;putStrLn.unlines$(o=<<b):(zipWith k b.w.s(p,p)$([id,f$f w,second$f w]!!)<\$>b)
o=show;f=first;w=tail

• Please add all the necessary imports, e.g. for randoms to your code (and byte count). If there's an interpreter that imports by default, refer to it in the language name.
– nimi
Commented Sep 7, 2016 at 23:07