# Motorcycle gear checker!

Some of you may be familiar with the way that a motorcycle shifts. But for those who don't, It looks like this

6

5

4

3

2

N

1

Now I want to know what gear I am in after performing a few up and down shifts. The program should work from neutral.

Sample input:

V^^


Sample output:

2


As you can see I downshifted once from N to 1 and upshifted twice to 2nd gear.

This is a code golf. Shortest answer in bytes wins.

Note: The input can be any 2 characters. Can be U and D for up and down or whatever you want it has to be a string. You cannot shift beyond 1st or 6th gear. If you are in 6th and upshift again it will stay in 6th. Good luck!

• Next time, please post your challenge to the sandbox to get feedback before posting it on main – fəˈnɛtɪk Feb 23 '17 at 13:56
• @seshoumara the only two requirement are that is has to be a string and that you can only input 2 characters. So could use a newline as a character. but If you'd use it for another reason, I don't really mind. it would be interesting to see what you have in mind. but give a short explaination as to why you've done it that way if you do. GL! – Martijn Vissers Feb 23 '17 at 14:39
• It's a shame this doesn't account for the half-step shift between 1 and N. It'd be neat to be able to not only go 2 N 1 N 2 3, but also go 2 1 N 2 3 – Cort Ammon Feb 23 '17 at 17:03
• I agree to @CortAmmon - there is a single shift between 1 and 2. It's half shift where the neutral is. – Džuris Feb 23 '17 at 20:29
• not all motorcycles shift like this. Most clutchless motorcycles shift in N-1-2-3-4 (or N-1-2-3 on some very ancient vehicles). They don't have gear 5 or 6 and use a round gear, i.e. when it's 4 then increasing the gear will make it wrap around to N. – phuclv Feb 24 '17 at 14:15

## JavaScript (ES6), 494847 46 bytes

Expects:

• 1 for down
• 7 for up
f=([c,...s],g=2)=>c?f(s,g-c&7||g):'1N'[--g]||g


### Formatted and commented

f = (                   // f is a recursive function which takes:
[c,                   // - c = next character in input string
...s],            // - s = remaining characters
g = 2                 // - g = current gear, with default = neutral = 2
) =>                    //
c ?                   // if there's still a character to process:
f(                  //   do a recursive call with:
s,                //     - the remaining characters
g - c & 7 ||      //     - the updated gear if it is valid
g                 //       or the previous gear if not
)                   //
:                     // else:
'1N'[--g] ||        //   decrement g and output '1' for g = 0, 'N' for g = 1,
g                   //   or simply the corresponding digit for other values


Gears are mapped as follows:

g MOD 8 = 0 1 2 3 4 5 6 7
---------------
gear    = X 1 N 2 3 4 5 6       (where 'X' is an invalid state)


Which allows us to easily check the validity of the current gear with:

(g & 7) != 0


### Demo

f=([c,...s],g=2)=>c?f(s,g-c&7||g):'1N'[--g]||g

console.log(f(''))
console.log(f('1'))
console.log(f('11'))
console.log(f('17777'))
console.log(f('1777777771'))

# 05AB1E, 22 20 bytes

Îvy<+®‚Z5‚W}6LÀ'N¸ìè


Try it online!

Explanation

Î                      # push 0 (accumulator) and input
v         }           # for each in input
y<+                  # decrement current element and add to accumulator
®‚Z               # take maximum of current value and -1
5‚W            # take minimum of current value and 5
6L         # push the range [1 ... 6]
À        # rotate left
'N¸ì    # prepend the letter "N" producing the list [N, 2, 3, 4, 5, 6, 1]
è   # index into this list with the value produced by the loop


# MATL, 3228 23 bytes

5 bytes saved thanks to @Luis

'234561N'j!Uq[aA]&Ys0))


This solution uses '2' for up-shift and '0' for down-shift.

Try it at MATL Online

Explanation

'234561N'   % Push the string literal to the stack
j           % Grab the input as a string
!U          % Convert the input to a numeric array based on the characters.
q           % Subtract 1 to turn '2' into 1 and '0' into -1
[aA]        % Push the array [-1 5] to the stack
&Ys         % Compute the cumulative sum using the array [-1, 5] as
% the upper and lower limits at each point
0)          % Get the last value from the cumulative sum
)           % Use this to index into the initial string literal.
% Implicitly display the result

• @Lifeless Updated with an explanation – Suever Feb 23 '17 at 14:16
• Very nice! may i ask why the string is 234561N instead of 1n23456 or 65432n1? I also found a flaw! If you keep upshifting it should stay in 6th gear but it returns N – Martijn Vissers Feb 23 '17 at 14:17
• Nice! Didn't know about the limits trick in cumsum – B. Mehta Feb 23 '17 at 16:36
• @B.Mehta Me neither! Luis recommended it – Suever Feb 23 '17 at 17:09
• @B.Mehta Also, feel free to join us over in the MATL chatroom! – Suever Feb 23 '17 at 17:13

# V, 20, 15 bytes

:sil!î¬61énÀxVp


Try it online!

Input is a string of h (up) and l (down) characters.

Thanks to @nmjcman for saving 5 bytes and teaching me about a vim feature I never knew about!

If we could assume the input never goes out of bounds, it would simply be 9 bytes:

¬61énÀxVp


But unfortunately that isn't allowed.

Explanation:

:sil!           " If the cursor goes out of bounds, ignore it and continue
î          " Run the following keystrokes as V code, rather than vimscript:
¬61       "   Insert the string "654321". This will leave the cursor on the '1'
én     "   Insert an 'n'
À    "   Run the first arg as V code. This will move left and right a bunch of times
x   "   Delete whatever character we ended up on
V  "   Select this whole line,
p "   And replace it with the character we just deleted

• Also, Try it online! V compression. That's cool. – nmjcman101 Feb 23 '17 at 17:52
• Actually, I think that this doesn't work because going over or under the 1/6 breaks the macro :/ – nmjcman101 Feb 23 '17 at 17:55
• Why is the 9 byte answer not allowed? – Albert Renshaw Feb 23 '17 at 19:10
• @AlbertRenshaw It fails if you ever attempt to shift beyond 1st or 6th gear. For example Try it online! should output n, not 1. – DJMcMayhem Feb 23 '17 at 19:11
• Oh I see, I thought by input is always valid you meant non-shifting characters. Still a cool answer even if its invalid – Albert Renshaw Feb 23 '17 at 19:18

# Java 7, 106105 103 bytes

char c(String s){int r=1;for(int c:s.toCharArray())r+=c<99?1:-1;return"1N23456".charAt(r<0?0:r>6?6:r);}


Explanation:

char c(String s){                // Method with String input and character return-type
int r = 1;                     // Result-index (0-indexed and starting at 1)
for(int c : s.toCharArray()){  // Loop over all characters in the input String
r += c < 99 ?                //  If the current character is '^':
1                     //   Raise the result-index by 1
:                       //  If it is 'v' instead:
-1;                   //   Decrease the result-index by 1
}
return "1N23456".charAt(       // Return the character based on the return-index:
r < 0 ?               //  If the result-index is below 0
: r > 6 ?       //  Else-if the result-index is above 6
:       //  Else
r);    //   Use the result-index
}


Test code:

Try it here.

class M{
static char c(String s){int r=1;for(int c:s.toCharArray())r+=c<99?1:-1;return"1N23456".charAt(r<0?0:r>6?6:r);}

public static void main(String[] a){
System.out.println(c("v^^"));
System.out.println(c("^^^^^^^^"));
System.out.println(c("vvvv^^^vvvv"));
System.out.println(c("^v^v^v^v"));
}
}


Output:

2
6
1
N


("1N23456"!!).foldl(\l c->max 0$min 6$l+read[c]-1)1


Uses 0 for down and 2 for up. Usage example:

(("1N23456"!!).foldl(\l c->max 0$min 6$l+read[c]-1)1) "0002"


Thanks to @xnor for taking off 6 bytes! Also, turns out I don't need a function name or parentheses so that's another 2 bytes.

• If you take the input chars as 0 and 2, you can do read[c]-2. – xnor Feb 23 '17 at 21:57
• Welcome to PPCG! Anonymous functions are fine too, so you don't need the g=. – Laikoni Feb 23 '17 at 22:20
• @Laikoni I'd have to wrap it in parentheses, right? That wouldn't change the byte count so I thought I'd leave the g= because it's clearer – user1472751 Feb 23 '17 at 22:40
• @user1472751 You don't need the parens. – Esolanging Fruit May 3 '17 at 3:27

# JavaScript (ES6), 48 58 bytes

s=>"1N23456"[[1,...s].reduce((a,b)=>a?a<6?+b?a+1:a-1:6:0)]


# Usage

Assign it to a function, and then call it. Input is a string containing a 1 for an upshift, and a 0 for a downshift.

f=s=>"1N23456"[[1,...s].reduce((a,b)=>a?a<6?+b?++a:a--:6:0)]
f("011")
-> "2"
f("0")
-> "1"
f("01")
-> "N"

• f(0) returns 1 not N... and your code returns undef if you shift up from 6 or down from 1 – fəˈnɛtɪk Feb 23 '17 at 14:28
• Good catch. Fixed at cost of two bytes – Luke Feb 23 '17 at 14:34
• Doesn't work input such as f("001") which should return N (gear down to 1, gear down staying at 1, gear up to N) – Emigna Feb 23 '17 at 14:35
• Not supposed to loop around. It should stay at 6 if upshifted from 6 and stay at 1 if downshifted from 1. Also, it still gives undef if you downshift from 1 – fəˈnɛtɪk Feb 23 '17 at 14:35

# PHP 7.1, 71 bytes

for(;$c=$argv[1][$i++];))$g=max(-1,min($g+=$c<=>X,5));echo N234561[$g];  shifts $g from -1 to 5, uses negative string offset for first gear.
Run with -nr, provide shifting string as command line argument.

# Jelly, 17 14 bytes

1;r2ị$¥/CỊ¡o”N  Uses 6 for up and0 for down. Try it online! ### How it works 1;r2ị$¥/CỊ¡o”N  Main link. Argument: s (string of 6's and 0's)

1;              Prepend a 1 (integer) to the string/character array s.
Let's call the arguments x and y.
r                 Construct the range [x, ..., y] (increasing or decreasing).
y will be a character, but 'r' casts both argument to int.
This is intended for use with floats, but it works just as well
when the argument is a digit.
$Create a monadic chain of two links: 2ị Take the second element of the constructed range. When y = 6 > x, this gives x + 1. When y = 0 < x, this gives x - 1. When y = x, the range is a singleton array, so this gives x. ¡ Conditional application: Ị If the previous result is insignificant (0 or 1): C Subtract it from 1. This swaps 0 and 1 without affecting the other potential outcomes. o”N Logical OR with 'N', replacing 0 with that character.  ## Ruby, 58 bytes ->s{a=1;s.chars{|b|a-=[a<=>0,a<=>6][b<=>?v]};"1N23456"[a]}  Expected input is 'v' for a downshift and '^' for upshift # Processing JS (modified) 121 bytes var g="1N23456",a="",c=0; for(var i=0;i<a.length;i++){if(a[i]==="d"&&c>0){c--;}else if(c<6&&a[i]==="u"){c++;}}println(g[c]);  Ungolfed var g=[1,"N",2,3,4,5,6],a="",c=0; for(var i=0;i<a.length;i++) {if(a[i]==="d"&&c>0) { c--; }else if(c<6&&a[i]==="u") { c++; } } println(g[c]);  Try it online! I went with PJs since I know it well. The only problem is the version I use is very strictly typed. I can't leave out brackets and lots of other tricks. It is pretty simple. The input should go into the variable a and it takes lowercase u d. The program loops until it hits the end of the string and every iteration it checks to see if it is a u or a d. If it is and it won't try and "shift" past where you can it shifts. At the end I print the results! • If your version allows ternary operators, you might be able to rewrite your ifs in a much more shorter fashion, I think. – Bojidar Marinov Feb 23 '17 at 16:38 • The input should go into the variable a Using hard coded input is not a default input method, see here. – Laikoni Feb 23 '17 at 16:51 • @Laikoni really? That is silly. I don't have any better way. If I have to redo this it will be ~100 bytes longer – Christopher Feb 23 '17 at 16:57 • Can't you simply wrap your code in a function? Eg. void f(String[] a){...} That's hardly 100 bytes. – Laikoni Feb 23 '17 at 17:07 • @Laikoni In Khan Academy ProcessingJS, it is pure JS, and hence doesn't have String or void. But you're right, a function would be way shorter – Kritixi Lithos Feb 23 '17 at 17:55 # k, 25 bytes "1N23456"@{6&0|x+y-92}/1,  It takes input as a string, and uses [ for downshift, and ] for upshift, because they're conveniently situated. "1N23456"@ / the numbers 0 to 6 are used for the gears, / this turns them into the correct number/letter 1, / prepend 1 because this is our initial gear { }/ / fold the function through the list / x is before, y is the next character y-92 / subtract 92, which is between "[" and "]" / "[" becomes -1 and "]" becomes 1 x+ / add it to what we had before 6&0| / use max and min to set boundaries 6 and 0  Examples:  shift:"1N23456"@{6&0|x+y-92}/1, shift"[]]" "2" shift"]]]]]]]]" "6" shift"[[[[]]][[[[" "1" shift"[][][][]" "N" shift"[[[[[[[[]" "N" shift"]]]]]]]][" "5"  ## GNU sed, 89 87 + 1(r flag) = 88 bytes Because sed has no integer types or arithmetic operations, the solution is arrived at by using regular expressions only. s:$:65432Nx1:
:
/6x/!s:^U(.*)(.)x:\1x\2:
s:^D(.*)x(.):\1\2x:
t
s:U|D::
t
s:.*(.)x.*:\1:


It works by sliding the pointer x based on each input shift, left (for Up) or right (for Down), along a non-wrapping tape that contains only the cells 65432N1. The answer at the end is the value in the cell left of the pointer.

Example run: or Try it online!

sed -rf gear.sed <<< "UUUUUUD"
5


Explanation:

s:$:65432Nx1: # assign initial tape and pointer : # start loop /6x/!s:^U(.*)(.)x:\1x\2: # if shift 'U', slide x to left, but not past the edge s:^D(.*)x(.):\1\2x: # if shift 'D', slide x to right, -||- t # repeat s:U|D:: # if a shift couldn't be applied, delete it "manually", t # and jump to the start of the loop again s:.*(.)x.*:\1: # print value left of pointer x (answer)  • Here is 76 bytes, but it outputs in unary. – Riley Feb 23 '17 at 17:31 • @Riley Unary, of course! Well, your solution is different, so why not post it! – seshoumara Feb 23 '17 at 17:38 • Yours gave me the inspiration for it. I figured I'd let you use it if you wanted. – Riley Feb 23 '17 at 18:09 • @Riley Then I'll make a separate section with your version and credit you. – seshoumara Feb 23 '17 at 18:12 • I'll just post my own :) – Riley Feb 23 '17 at 18:12 # GNU sed, 76 73 bytes Includes +1 for -r s/$/1/
:
/1{6}/!s/^U(.*)/\11/
s/^D(.*)1/\1/
t
s/U|D//
t
s/^1$/N/ s/^$/1/


Output is in unary except neutral, which is still N (see this consensus).

Try it online!

This basically counts up and down in unary then converts 1 to N and 0 to 1.

s/$/1/ # add 1 to the end (the starting value) : # loop start /1{6}/!s/^U(.*)/\11/ # If the string starts with 'U' and doesn't have 6 ones, increment s/^D(.*)1/\1/ # If the string starts with 'D' decrement (but not past 0) t # if something changed loop back s/U|D// # if the U or D couldn't be applied, remove it. t # if something changed loop back s/^1$/N/             # replace 1 with N
s/^$/1/ # if "0", replace with 1  • Your sed version can be shorter by 4 bytes I think, if you work with 1 as the starting value, as N, and nothing as 1. s/$/1/;:;/1{6}/!s/^U(.*)/\11/;s/^D(.*)1/\1/;t;s/U|D//;t;s/^1$/N/;s/^$/1/ – seshoumara Feb 23 '17 at 18:47

# Rebol, 96 93 bytes

f: func[s][g: next"1N23456"parse s[any["D"(g: back g)|"U"(unless tail? x: next g[g: x])]]g/1]


Ungolfed:

f: func [s] [
g: next "1N23456"
parse s [
any [
"D" (g: back g)
| "U" (unless tail? x: next g [g: x])
]
]
g/1
]


Example usage (in Rebol console):

>> print f "DUU"
2

>> print f "DDDUU"
2

>> print f "UUUUUUUUU"
6

>> print f "UUUUUUUUUD"
5


# ><>, 35 bytes

An enthusiastic piece of code that encourages you to drive above the speed limit.

Accepts any two inputs whose code modulo 3 are 0 and 2, for example 0 and 2.
For extra fishiness, I recommend the use of < and >.

1i:0(?;3%1-+:0(?0:6)?6:1go!
1N23456


Explanation :

1i:0(?;3%1-+:0(?0:6)?6:1go!
1                             # initial position
i                            # read the next char
:0(?;                       # copies it, test copy against 0, if lower stops (EOF detection)
3%1-                   # map the char to -1 or 1
+                  # add it to the position
:0(?0             # if the new position is lower than 0, set to 0
:6)?6        # if the new position is greater than 6, set to 6
:1go    # output a character from line 1 at the position
!   # loops and skip the position initialisation


You can try it here !

# SpecBAS - 102

1 g=2: INPUT s$2 FOR i=1 TO LEN s$
3 g+=(s$(i)="^" AND g<7)-(s$(i)="v" AND g>1)
4 NEXT i
5  ?"1N23456"(g)


Moves the index of the string depending on input and prints the relevant character.

# Pyth, 32 bytes

J1VQ=JhtS[06+J-qNbqNd;?qJ1\N?JJ1


Uses space and newline for down and up.

Explanation

J1VQ=JhtS[06+J-qNbqNd;?qJ1\N?JJ1
J1                                 Initialize J to 1
VQ                 ;             For each character in the input
+J-qNbqNd              Increment or decrement J
htS[06                       Get the middle sorted value of [0,6,J]
=J                             Assign it to J
?qJ1\N?JJ1   Change 1 to 'N' and 0 to 1


There's almost certainly a better way to do the incrementing and the output.

# CJam, 24 22 bytes

"1N23456"1q{~0e>6e<}/=


Uses ( for down and ) for up.

Try it online!

Explanation

"1N23456"               e# Push the string containing all gears
1              e# Push 1, the initial index
q             e# Push the input
{            e# For each character in the input
~           e#   Eval that character. ( is decrement and ) is increment.
0e>        e#   Take the maximum of (0, index)
6e<     e#   Take the minimum of (6, index)
}/   e# (end of block)
=  e# Take that index of the string


## Batch, 144 bytes

@set/ps=
@set g=1
:l
@if %g% neq %s:~,1% set/ag+=%s:~,1%/3-1
@set s=%s:~1%
@if not "%s%"=="" goto l
@if %g%==1 (echo N)else cmd/cset/ag+!g


Takes input on STDIN, using 0 to go to a lower gear and 6 to go to a higher gear. These numbers were chosen to make it easy to ignore the current gear. Finally if the gear is 1 then N is printed otherwise 0 is converted to 1 and the gear is printed.

# Javascript ES6 nonstrict, 136 120 chars

## 136 chars for V^

with({get x(){return Math.max(0,Math.min(y,6))},set x(v){y=v}})f=s=>eval(s.replace(/(V)|./g,(m,v)=>x${"-+"[+!v]}=1,,y=1)+'"1N"[x]||x')  with({get x(){return Math.max(0,Math.min(y,6))},set x(v){y=v}}) f=s=>eval(s.replace(/(V)|./g,(m,v)=>x${"-+"[+!v]}=1,,y=1)+'"1N"[x]||x')
console.log(f("V^^"))

## 120 chars for -+

with({get x(){return Math.max(0,Math.min(y,6))},set x(v){y=v}})f=s=>eval(s.replace(/./g,m=>x${m}=1,,y=1)+'"1N"[x]||x')  with({get x(){return Math.max(0,Math.min(y,6))},set x(v){y=v}}) f=s=>eval(s.replace(/./g,m=>x${m}=1,,y=1)+'"1N"[x]||x')
console.log(f("-++"))

# Retina, 65 bytes

^
1 N23456
+( (.)?(\w*6)u
$1$2
)(.)? (\w*6)d
$1$2
.* (.).*
$1  Uses u and d for up and down. Try it online! Explanation This program works by keeping 1N23456 behind the sequence of instructions. It keeps track of the current gear by having a space behind it. Then it takes one instruction at a time until there's no more. ^ 1 N23456  Start by putting 1 N23456 before the input. The space before N indicates that N is the current gear. +( (.)?(\w*6)u$1 $2 )(.)? (\w*6)d$1$2  These are two replacement stages, grouped together, and run until they stop changing the string:  (.)?(\w*6)u$1 $2  The first one handles shifting the gear up. It will look for any number of gears after the space, followed by a 6, then followed by u (u indicates the instruction to gear shift up). If there were characters before the 6, it swaps the space with the character immediately after it, deletes the u, and leaves the rest of the string intact. Since the 6 is mandatory in the match, it will only swap the space with any character before the 6. It will never swap with the 6. (.)? (\w*6)d$1$2  The second stage handles gear shifting down, and works similarly. It looks optionally for a character before the space, then some other gears after ending in 6, followed by d. It swaps the space with the character before it, deletes the d, and leaves the rest intact. If the space was at the start of the string, there was no match for a character before the space, so no swap occurs. .* (.).*$1


After neither of the above replacements can be done anymore, all gear shifts have been completed. The line is cleared of everything except the gear immediately after the space. This is the final gear.

# Powershell, 11287 85 bytes

$i=1;switch([char[]]$args[0]){'^'{if(5-gt$i){$i++}}'v'{if(1-le$i){$i--}}}'1N2345'[$i] ungolfed $i=1;                                # index which gear we are in
switch([char[]]$args[0]){ # loop over all elements using a switch '^'{if(5-gt$i){$i++}} # if there is a ^ and we are not in sixth yet, shift up 'v'{if(1-le$i){$i--}} # if there is a v and we are not in first, shift down } '1N2345'[$i]                         # print the output


saved 25 bytes by reading the powershell codegolf tips

saved 2 bytes by flipping the gt/le operators

Perl 6, 144 bytes

my enum C <1 N 2 3 4 5 6>;my $n=prompt("");my$p=1;for split("",$n) ->$l {$l eq "u" &&$p < 6 ?? ++$p !! 0;$l eq"d"&&$p>0 ?? --$p!!0};say C(\$p);


Works as it should, i believe. Improvements are welcome. First time using Perl for anything, but i loved the thought of the language, so i had to try.

# Clojure, 74 bytes

#((vec "1N23456")(reduce(fn[c s](max 0(min 6((if(= s \^)inc dec)c))))1 %))


Folds over the shift string, maintaining an index as the accumulator. Each iteration it either increases or decreases the index, then clamps it to the range 0-6. Finally, a string holding the gears is indexed and returned.

Returns a Clojure character representing the current gear. Gear 1 is returned as \1, and gear 'N' is returned as \N.

; Expects ^ for shift-up, and V (or anything else) for shift down
; Returns a character representing the current gear
(defn shift [shift-str]
((vec "1N23456") ; 4. Then index the gear list with the calculated index, and return
(reduce (fn [current-gear s] ; 1. Fold over the shift symbols
(max 0 (min 6 ; 3. Clamp it to the range 0-6 so we don't overflow
((if (= s \^) inc dec) ; 2. If the shift is up, increase, else decrease
current-gear))))
1
shift-str)))


# Python 3, 67 63 bytes

k=1
for i in input():k+=[k<6,-(k>0)][i<'1']
print('1N23456'[k])


Pretty straightforward solution.

-4 bytes thanks to @ovs!