Stack Exchange Vote Simulator

Write a program or function that takes in a string only containing the characters ^ and v (you can assume there will be no other characters). Read from left to right this string represents the sequence of mouse clicks a single user made while viewing a Stack Exchange question or answer for the first time.

Every ^ represents a click of the upvote button and every v represents a click of the downvote button. (For working examples look slightly left.)

Assume that no voting limitations are in effect so all the clicks are registered correctly.
Print or return:

• 1 or +1 if the post ends up being upvoted.
• 0 if the post ends up not being voted on. (-0 and +0 are not valid)
• -1 if the post ends up being downvoted.

Net Votes Before    Button Pressed    Net Votes After
1                   ^                 0
1                   v                 -1
0                   ^                 1
0                   v                 -1
-1                  ^                 1
-1                  v                 0


The shortest code in bytes wins.

Test cases:

[empty string] -> 0
^^ -> 0
^v -> -1
^ -> 1
v -> -1
v^ -> 1
vv -> 0
^^^ -> 1
vvv -> -1
^^^^ -> 0
vvvv -> 0
^^^^^ -> 1
vvvvv -> -1
^^^^^^ -> 0
vvvvvv -> 0
^^v -> -1
^v^ -> 1
^vv -> 0
vv^ -> 1
v^v -> -1
v^^ -> 0
^vvv^^vv^vv^v^ -> 1
^vvv^^vv^vv^v^^ -> 0
^vvv^^vv^vv^v^^^ -> 1
^vvv^^vv^vv^v^^v -> -1
^vvv^^vv^vv^v^^vv -> 0
^vvv^^vv^vv^v^^vvv -> -1
^vvvvvvvvvvvv -> 0
^^vvvvvvvvvvvv -> 0
^^^vvvvvvvvvvvv -> 0
vvv^^^^^^^^^^^^ -> 0
vv^^^^^^^^^^^^ -> 0
v^^^^^^^^^^^^ -> 0

• What? no side voting? Geoborts and Seadrus are sad Nov 9 '15 at 7:48
• Dear Secret SE Developer: Congratulations on successfully duping your own community into making site improvements for you... ;) Nov 10 '15 at 9:58
• I've been starring at the example table for a while now and I still don't get the test cases. a post with a score of 1 gets up-voted and it then has a score of 0. And a post with a score of 0 gets up-voted to have a score of 1. And post with a score of -1 gets up-voted to have a score of 1. So the ^ character can cause a -1, +1 or +2 score change? Am I dense where? What's going on?
Nov 11 '15 at 18:18
• @Brad I suggest you try the actions with some actual post (e.g. this question itself). Upvoting a post you already upvoted undoes the upvote. Same with downvoting. Nov 11 '15 at 18:23
• I wonder what the real-time votes on this question was. I'm willing to bet a lot of people used this question as a test case. Nov 11 '15 at 18:46

Gol><> 0.3.11, 1312 11 bytes

iEh^=:@)+M


Try it online. Even though this will work fine in the next update, I've listed it as 0.3.11 just in case.

Explanation

i               Read char
Eh             If EOF, halt and output top of stack as num
^=          Push 1 if char is ^, else 0
:@        Dup and rotate, giving [is^ is^ votecount]
)       Compare greater than, pushing 1 or 0 as appropriate


Note that the first use of @ pulls a 0 from the bottom of the stack to initialise the vote count for the first iteration

To illustrate with a full table:

Votes before    Button    Is ^?    Compare <    Add     Subtract 1
1            ^         1         0          1          0
1            v         0         0          0         -1
0            ^         1         1          2          1
0            v         0         0          0         -1
-1            ^         1         1          2          1
-1            v         0         1          1          0

• ....dang! Nice one! Nov 9 '15 at 3:53

JavaScript (ES7), 4746444337 36 bytes

Crossed out 44 is still regular 44 :(

s=>[for(x of s)s=x<"v"?s!=1:!~s-1]|s


Keeps a running total in s. Uses for of loop to iterate over each character in the string and updates s based on current character and previous value.

Edits: Golfed ~s&&-1 to !~s-1. This expression has to equal 0 if s equals -1 and -1 otherwise. Saved 6 bytes thanks to @nderscore.

How the expression works:

 ~s    // Bitwise inverse. ~s==0 only if s==-1
!      // Logical negate. Casts to boolean. Equivalent to s==-1
-1  // Subtract. Casts to number so true-1 is 1-1 and false-1 is 0-1

• I got it down to 37 bytes: v=>[for(x of v)v=x<"v"?~~v<1:!~v-1]|v Nov 9 '15 at 22:01
• @nderscore Hey, that's great. I thought the extra variable was clumsy, but didn't think I could eliminate it. Nov 9 '15 at 22:21
• Crossed out 44 is still regular 44... Jan 8 '16 at 23:27
• Weren't array comprehensions removed from the spec?
– bren
Apr 13 '16 at 20:51

x86 machine code, 24 bytes

31 C0 8A 11 84 D2 75 07 C0 E0 02 C0 F8 06 C3 41 38 C2 74 EC 88 D0 EB EA


This is a function using the fastcall calling convention, which takes a string and returns an 8-bit integer.

I tested it with the following C program, which must be compiled for 32-bit mode.

#include <stdio.h>
#include <inttypes.h>

__attribute__ ((aligned (16))) const unsigned char fun[] = {

0x31,  //xor eax,eax
0xC0,
0x8A, //mov [ecx],dl
1 | 2<<3,
0x84, //test dl, dl
0xC0 | 2<<3 | 2,
0x75, // jnz
7,
0xC0, //shl al 2
0xC0 | 4<<3,
2,
0xC0, //sar al 6
0xC0 | 7<<3,
6,
0xC3, //ret
0x41, //inc ecx
0x38, //cmp al,dl
0xC0 | 2,
0x74, //je
-20,
0x88, //mov dl,al
0xC0 | 2<<3,
0xEB, //jmp
-22,
};

int main()
{
char* s[] = {
"",
"^^",
"^v",
"^",
"v",
"v^",
"vv",
"^^^",
"vvv",
"^^^^",
"vvvv",
"^^^^^",
"vvvvv",
"^^^^^^",
"vvvvvv",
"^^v",
"^v^",
"^vv",
"vv^",
"v^v",
"v^^",
"^vvv^^vv^vv^v^",
"^vvv^^vv^vv^v^^",
"^vvv^^vv^vv^v^^^",
"^vvv^^vv^vv^v^^v",
"^vvv^^vv^vv^v^^vv",
"^vvv^^vv^vv^v^^vvv",
"^vvvvvvvvvvvv",
"^^vvvvvvvvvvvv",
"^^^vvvvvvvvvvvv",
"vvv^^^^^^^^^^^^",
"vv^^^^^^^^^^^^",
"v^^^^^^^^^^^^",
};

for(int i = 0; i < sizeof(s)/sizeof(*s); i++)

printf("\n%d\n", sizeof(fun));
for(int i = 0; i < sizeof(fun); i++)
printf("%02X ", fun[i]);
return 0;
}

• Is this allowed? I mean I could also write the whole thing in C and just say the C code requires an empty file for performing the task while saying my code is the framework making my code becoming 0bytes. Why is that diferent from your solution? Jul 12 '16 at 9:29
• @Zaibis Because my solution contains the code that solves the challenge? See meta.codegolf.stackexchange.com/a/1071/30688. Jul 12 '16 at 9:37

CJam, 18 14 bytes

Updated version with significant improvements contributed by Dennis:

0'jqf{-g_@=!*}


Try it online

Explanation:

0     Start value for running total.
'j    Push character between '^ and 'v for use in loop.
q     Get input.
f{    Apply block with argument to all input characters.
-     Subtract character from 'j. This will give -12 for '^, 12 for 'v.
g     Signum, to get 1 for '^, -1 for 'v, which is our increment value.
_     Copy increment value.
@     Bring running total to top.
=     Compare. This will give 1 for the -1/-1 and 1/1 combinations where the new
running total is 0. Otherwise, the new running total is the increment value.
!     Negate to get 0 for the -1/-1 and 1/1 cases.
*     Multiply result with increment value, to get new running total.
}     End block applied to input characters.


brainfuck, 146 bytes

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


This program takes each byte of input and compares it against the last. If they're the same, it throws the input away and stores "0" as the "previous input", otherwise it saves it normally.

If the final result is v, it prints -. If the final result was non-zero, 1 is added to an empty cell. Finally, 48 is added to that cell and it is printed.

Javascript ES6, 91 48 chars

s=>~~{'^':1,v:-1}[s.replace(/(.)\1/g).slice(-1)]


Explanation: undefined ends by d.

Test:

 -> 0
^^ -> 0
^v -> -1
^ -> 1
v -> -1
v^ -> 1
vv -> 0
^^^ -> 1
vvv -> -1
^^^^ -> 0
vvvv -> 0
^^^^^ -> 1
vvvvv -> -1
^^^^^^ -> 0
vvvvvv -> 0
^^v -> -1
^v^ -> 1
^vv -> 0
vv^ -> 1
v^v -> -1
v^^ -> 0
^vvv^^vv^vv^v^ -> 1
^vvv^^vv^vv^v^^ -> 0
^vvv^^vv^vv^v^^^ -> 1
^vvv^^vv^vv^v^^v -> -1
^vvv^^vv^vv^v^^vv -> 0
^vvv^^vv^vv^v^^vvv -> -1
^vvvvvvvvvvvv -> 0
^^vvvvvvvvvvvv -> 0
^^^vvvvvvvvvvvv -> 0
vvv^^^^^^^^^^^^ -> 0
vv^^^^^^^^^^^^ -> 0
v^^^^^^^^^^^^ -> 0
.split("\n").map(s => s.split(" -> "))
.every(([s,key]) => (s=>~~{'^':1,v:-1}[s.replace(/(.)\1/g).slice(-1)])(s)==key)


s=>({'':0,'^':1,v:-1}[s.replace(/^(.)\1(\1\1)*(?=.?$)|.*(.)(((?!\3).)\5)+/,"").substr(-1)]) s=>~~{'^':1,v:-1}[s.replace(/^(.)\1(\1\1)*(?=.?$)|.*(.)(((?!\3).)\5)+/,"").substr(-1)]
s=>~~{'^':1,v:-1}[s.replace(/^.*(.)(((?!\1).)\3)+|(.)\4(\4\4)*/,"").substr(-1)]
s=>~~{'^':1,v:-1}[s.replace(/^.*(.)(((?!\1).)\3)+|(.)\4(\4\4)*/,"").slice(-1)]
s=>~~{'^':1,v:-1}[s.replace(/.*(.)(((?!\1).)\3)+|(.)\4(\4\4)*/,"").slice(-1)]
s=>~~{'^':1,v:-1}[s.replace(/.*(.)(((?!\1).)\3)+|((.)\5)*/,"").slice(-1)]
s=>~~{'^':1,v:-1}[s.replace(/((.)\2)+/g,"!").slice(-1)]
s=>~~{'^':1,v:-1}[s.replace(/(.)\1/g,"!").slice(-1)]
s=>~~{'^':1,v:-1}[s.replace(/(.)\1/g,0).slice(-1)]
s=>~~{'^':1,v:-1}[s.replace(/(.)\1/g).slice(-1)]


Befunge 93 - 55 bytes

vj#p01:>#<:1+|
>~:10g-|v:g25<
^p01"j"<1^   <
./*34-g0<@


52 characters and 3 new lines.

Tested on this interpreter.

The j is equidistant from ^ and v in ascii so it's used to make arithmetic conversions in the end, rather than space consuming conditionals.

Python 2, 49

lambda s:reduce(lambda x,c:cmp(cmp('u',c),x),s,0)


Iterates through with the update function

lambda x,c:cmp(cmp('u',c),x)


that takes the current vote count x and the new character c and outputs the new vote count.

The idea is to use Python 2's cmp function, which compares its two args and gives -1, 0, 1 for <, ==, > respectively. The inner one cmp('u',c) gives -1 for v and 1 for ^; any character between them suffices for 'u'. The outer one then compares that to x, which gives cmp(1,x) for ^ and cmp(-1,x) for v, which have the right values.

Direct iteration was 3 chars longer (52), though would be one char short (48) if taking an input() with quotes was allowed.

x=0
for c in raw_input():x=cmp(cmp('u',c),x)
print x


The best recursive function I found was one char longer (50)

f=lambda s:len(s)and cmp(cmp('u',s[-1]),f(s[:-1]))


Prolog, 159 152 bytes

Code:

v(1,^,0).
v(1,v,-1).
v(0,^,1).
v(0,v,-1).
v(-1,^,1).
v(-1,v,0).
r(X,[H|T]):-T=[],v(X,H,Z),write(Z);v(X,H,Z),r(Z,T).
p(S):-atom_chars(S,L),r(0,L).


Test it yourself:
Online Interpreter here

Example

>p("^vvv^^vv^vv^v^^vvv").
-1

>p("^vvv^^vv^vv^v^")
1


Edit: Saved 7 bytes by unifying r-clauses with OR.

• Hmm. It seems like you could save quite a few bytes by redefining operators instead of defining functions (if that counts as a function under PPCG's rules?) May 29 '18 at 12:20
• @ASCII-only: Yeah. Hadn't learned that trick when I wrote this :) May 29 '18 at 12:36

CJam, 16 bytes

0reW=(2%*c'a--g


This will crash after printing 0, if applicable. The error can be suppressed with the Java interpreter. If you try this online, ignore everything but the last line of output.

How it works

0                e# Push a 0 on the stack.
r               e# Read a whitespace-separated token from STDIN.
e             e# Perform run-length encoding.
W=           e# Select the last [repetitions character] pair.
e# This will fail for the empty string, so the
e# interpreter will print the stack's only element (0).
(          e# Shift out the number of repetitions.
2%        e# Compute its parity.
*       e# Create a string, repeating the character 1 or 0 times.
c      e# Cast to character.
e# This will fail for a zero-length string, so the
e# interpreter will print the stack's only element (0).
'a-   e# Subtract the character 'a' from '^' or 'v'.
-  e# Subtract the difference (integer) from 0.
g e# Apply the sign function.


Python 2, 177 159 72 bytes

Still kinda new to this code golf thing.

def v(s):
c=0
for i in s:c=((0,1)[c<1],(0,-1)[c>-1])[i=="^"]
return c


EDIT: Fixed the incorrect behavior.
EDIT 2: Thanks @MorganThrapp for shaving off lots of bytes.

• You can shorten it to def v(s): c=0 for i in s:c=((0,1)[c<1],(0,-1)[c>-1])[i=="^"] return c. That's 72. Nov 10 '15 at 14:33
• @MorganThrapp Thanks, I didn't know about the (,)[] thing. Nov 10 '15 at 14:45
• Yeah, it's super helpful. If you haven't yet, read the tips for golfing in Python thread. Nov 10 '15 at 14:46
• That indentation isn't quite right, I just suggested an edit with the right indentation. You can't format code in comments, so it was wrong in mine. Nov 10 '15 at 14:49
• I believe this should be either i!="^" or i=="v". You can also use the fact that True/False corresponds to 1/0 for 60 bytes
– Jo King
Jan 28 at 3:12

JavaScript (ES6), 645958 52 bytes

f=v=>(t=/\^*$|v*$/.exec(v)[0]).length*(t<'v'?1:-1)%2


This is based on the observation that only the last stretch of the repetition (of either ^ or v) affects the result.

Thanks to Neil for golfing off 6 bytes.

• Why do you need the captures? Seems to me f=v=>(t=/\^*$|v*$/.exec(v)[0]).length*(t<'v'?1:-1)%2 suffices.
– Neil
Nov 10 '15 at 12:57
• @Neil: I'm not aware of array being coerced to the first element in > or < operator. Thanks for the tips Nov 11 '15 at 2:45
• No type coercion involved, I merely moved the [0] which may have confused you.
– Neil
Nov 11 '15 at 8:34
• @Neil: Oh, I indeed am confused. I didn't realized that you have moved it inside, I thought it was f=v=>(t=/\^*$|v*$/.exec(v))[0].length*(t<'v'?1:-1)%2, which works due to type coercion with array. Nov 11 '15 at 8:51

1%'^'=0
_%'^'=1
1%_=-1
_%_=0
v=foldl(%)0

• You can cut all the spaces by defining f as an infix function %. Also, I think the v can be a _.
– xnor
Nov 10 '15 at 10:22
• Actually, doesn't this give -1 for vv instead of 0?
– xnor
Nov 10 '15 at 10:28
• Oh, I always forget about infixes. Thanks for the spot, missed the inner inversion. Nov 10 '15 at 15:31
• Save 3 characters by replacing the third line (15 characters) with 1%_=-1 _%_=0, 12 characters. Nov 10 '15 at 22:28
• Okay right, now that's become shorter. Nov 11 '15 at 10:38

Scala, 75 bytes

def d(s:String)=s./:(0){case(1,94)|(-1,'v')=>0;case(_,94)=> 1;case _=> -1}


Test for implemented function.

  object Util {
def d(s: String) = s./:(0) {
case (1, '^') | (-1, 'v') => 0
case (_, '^') => 1
case (_, _) => -1
}
def main(s: Array[String]): Unit = {
println("1 == " + d("^vvv^^vv^vv^v^^^"))
println("1 == " + d("^vvv^^vv^vv^v^"))
println("-1 == " + d("^vvv^^vv^vv^v^^vvv"))
println("0 == " + d("^^^vvvvvvvvvvvv"))
println("0 == " + d("vvv^^^^^^^^^^^^"))
}
}

• Welcome to PPCG! Could you please add an explanation and/or an ungolfed version? Nov 12 '15 at 11:57

APL, 17

(⊣×≠)/⌽0,2-'^ '⍳⍞


For interpreters without fork notation (like GNU APL), it would be {⍺×⍺≠⍵}/⌽0,2-'^ '⍳⍞ (19). This is probably the most boring of possible solutions because it works directly from the definition of the problem.

Ruby, 41 35 bytes

Regex. Only the last button pressed is interesting, so check the run-length of that. Then compare it to "a" (or any letter between ^ and v) to get 1 or -1.

->s{s[/(.?)\1*$/].size%2*(?a<=>$1)}


C# 6, 18 + 80 = 98 bytes

Requires:

using System.Linq;


Actual function:

int S(string v)=>v.Split(new[]{"^^","vv"},0).Last().Length<1?0:v.Last()<95?1:-1;


How it works: the code first removes everything before the last ^^ or vv. That content is not relevant because clicking the same button twice will always cancel your vote. It does this by splitting on ^^ and vv and taking the last item. If this item is an empty string (.Length<1), then the function returns 0 because all voting has been cancelled. If the string it not empty, then it just looks at the last char of the original string: it will override all previous votes. If the char code is smaller than 95, then it will be 94, ^, so it returns 1, otherwise -1.

Python 2.7, 7975 88

s=input()
print (0,(1,-1)[s[-1]=='v'])[len(s[s.rfind(('v^','^v')[s[-1]=='v'])+1:])%2!=0]

• This doesn't actually print anything. Nov 9 '15 at 21:14
• Running it in my interpreter, it shows the output of the last line Nov 9 '15 at 21:18
• That's because you're running it in the REPL. You need to provide a full program that will work outside the REPL. Nov 9 '15 at 21:18
• Also, you can shorten that ternary to (-1,(1,0)[n==0])[n>0] to save 10 bytes. Also, don't use a=str.count. It actually costs you 4 bytes. Nov 9 '15 at 21:20
• That produces -1 for n=0, but cool syntax Nov 9 '15 at 21:21

Minkolang 0.11, 28 22 bytes

0$I2&N."j"o-34*:dr=,*!  Try it here. Explanation 0 Push a 0 (running total)$I                       Push length of input
2&N.                   Output as integer and stop if this is 0
"j"                Push 106
o               Take character from input (94 for ^, 118 for v)
<<so ^ becomes +12 and v becomes -12>>
-              Subtract
34*:          Divide by 12
d         Duplicate top of stack
r        Reverse stack
=,      Push 0 if equal, 1 otherwise
*     Multiply
<<this handles two of the same vote in a row>>
!    Unconditional trampoline (jumps the 0 at the beginning)


Note that there is no N. at the end. That's because I let it wrap around to the beginning. When the input is empty, the final tally is output as integer and the program stops.

Pyth, 13 bytes

ut+Jq\^H>JGzZ


Mathematica, 60 bytes

Mod[#,2]Sign@#&@Tr@Last@Split@StringCases[#,{"^"->1,_->-1}]&

• @#&? That's useless (unless Sequences are involved, but Sequences are not involved. Apr 13 '16 at 17:32

Shape Script, 26 bytes

"^"$"0>1@-"~"v"$"0<1-"~0@!


How it woks:

"^"$split input on '^' " 0> Check if the number is more than 0 (1 if true, 0 if false). 1@- subtract the answer from one. "~ Join it back together, with this string in place of '^' "v"$     Split on 'v'
"
0<         Check if 0 is more than the number (1 if true, 0 if false).
1-         subtract one from the results
"~       Join it back together, with this string in place of 'v'
0@       add a zero to the stack and place it under the string just built.
!        run the string as code


C# 6, 18 + 97 95 = 115 113 bytes, no string methods, excessive LINQ

int v(string s)=>(int)s.Reverse().TakeWhile((c,i)=>i<1||c==s[s.Length-i])?.Sum(x=>x<95?1:-1)%2;


Truly deserves to be preceded by

using System.Linq;


Got the idea of using x<95?1:-1 instead of x=='^'?1:-1 from ProgramFOX's answer

Coincidences:

• The tweak I stole makes use of comparing to 95 – the byte count excluding the using statement, using said tweak
• The sum of the digits of the total byte count equals the number of digits of the total byte count written as roman numeral

C: 67 66 Bytes

golfed:

void f(char *v){int i=0,c,s=0;for(;v[i]!=0;i++){v[i]>94?s--:s++;}}


ungolfed:

void f (char *v)
{
int i = 0, c, s = 0;

for (;v[i]!=0;i++)
{
v[i] > 94 ? s-- : s++;
}
}

• This does not return a result. It does not pass all tests. Jul 3 '17 at 10:33

Go, 179 bytes

An extremely naive solution.

package main
import(."fmt"."strings")
func main(){a:=""
i:=0
Scanln(&a)
b:=Split(a,"")
for _,e:=range b{switch i{case 1:i--
case 0:if e=="^"{i++}else{i--}
case-1:i++}}
Println(i)}

Ungolfed:

package main

import (
."fmt"
."strings"
)

func main() {
a := ""
i := 0
Scanln(&a)
b := Split(a, "")
for _, e := range b {
switch i {
case 1:
i--
case 0:
if e == "^" {
i++
} else {
i--
}
case -1:
i++
}
}
Println(i)
}

Perl 5, 41 bytes

40 bytes, plus 1 for -p

/(.)\1*$/;$_=((length$&)%2)*($1=~v?-1:1)


/(.)\1*$/; compares the input string to the regex /(.)\1*$/, i.e. sees whether it ends with a single character repeated some number ≥1 of times.

If so, $& is the whole repetition string and $1 is the character; otherwise (i.e. the input string is empty), those two variables are the empty string.

$1=~v?-1:1 compares $1 to the regex v and returns −1 if it matches and 1 otherwise.

And multiply that ±1 by (length$&)%2, the length of $& modulo 2.

05AB1E, 1412 11 bytes

Îvy'^QDŠ‹+<


NOTE: @Grimy already posted a shorter 8 bytes alternative for 05AB1E, so make sure to upvote him!

Explanation:

Î            # Push 0 (later mentioned as r) and the input-string
v           # Loop over the characters of the input:
y'^Q      '#  Does the current character equal "^"?
#  (results in 1 for truthy; 0 for falsey - later mentioned as b)
D      #  Duplicate this result b
Š     #  Triple swap (r,b,b) to (b,r,b)
‹    #  Check if the boolean b is smaller than the result-integer r
#  (again results in 1 for truthy; 0 for falsey)
<  #  Decrease this by 1
# (Implicitly output the result-integer r after the loop)


05AB1E, 8 bytes

γ¤®öÓÆ.±


Try it online!

Alternative solutions with the same length: uγ¤®öÓÆ(, γ¤®ögÓÆ(.

• This doesn't work. Neither your posted code nor the code in the TIO link (which is different) take into account votes like ^^ -> 0 May 8 '19 at 14:40
• @Emigna thanks for pointing it out! I fixed the code, it’s still 8 bytes. May 8 '19 at 22:52

CJam, 27 24 bytes

'^_]r+eW=(2%\(i99-g@*W*


All I took from Dennis' answer is g (sign function) .

Ruby, 43

->s{a=0
s.bytes{|i|b=9-i/11;a=a!=b ?b:0}
a}


9-i/11 evaluates to 1 or -1 when given the ascii codes of ^ (94) or v (118)

In test program:

f=->s{a=0
s.bytes{|i|b=9-i/11;a=a!=b ?b:0}
a}

g=gets.chomp
puts f[g]
`