g | x | w | all
Bytes Lang Time Link
010AWK250908T162755Zxrs
018Python 3230624T063638ZRhaixer
008x8616 machine code190101T181906Z640KB
006J230623T014119Zsouth
003Vyxal230623T034039ZBubbler
014JavaScript230622T150347ZShaggy
008Vyxal221017T112715ZDialFros
016shell portable/POSIX190818T200424Zuser9289
055R181231T224413ZSumner18
177CINTERCAL190819T052357ZJakob
010Runic Enchantments190819T151312ZDraco18s
034BrainFlak190818T211258ZEdgex42
819JavaScript V8 19 Bytes190819T141117Zpixma140
018Java JDK190819T102235ZCuttingC
003MathGolf190819T093521Zmaxb
012Zsh190818T040744ZGammaFun
8128Keg190813T080850Zuser8505
042brainfuck190816T021036ZJo King
021ed190814T175126Zroblogic
009><>190814T171510Zsquid
014jq190813T100855Zmanatwor
007Gema190813T095416Zmanatwor
019Zsh190812T234547Zroblogic
010Triangular190813T182629Zsquid
022Bash190813T160310ZDigital
008dc190813T155448ZDigital
015PowerShell190813T153721ZVeskah
004Gaia190813T082130ZEdgex42
6444Commodore BASIC PET190812T203824ZShaun Be
01233190813T091103ZTheOnlyM
040Whitespace190813T085157ZKevin Cr
00305AB1E190813T084034ZKevin Cr
016@190813T083325Zuser8505
004Stax190813T003445Zrecursiv
010Perl 5 p190813T010230ZXcali
003Stax190812T201132ZOliver
002Japt190812T200735ZOliver
005APL Dyalog Unicode190101T181110ZFrownyFr
050Homespring181231T203054ZBadAtPer
015SmileBASIC181231T185336Z12Me21
013Vitsy151128T183129ZAddison
1516Unefunge 98151128T182255ZThe Fift
011QBasic150529T220205ZDLosc
021Fission150528T171256ZBrainSte
013Tr150520T131104Zmanatwor
016Sed150520T130014Zmanatwor
022C150516T111615ZSpikatri
028Befunge150520T123945ZSean Lat
086Ruby150517T040722Zhistocra
018Haskell150518T220615Znimi
012VBA Excel150518T211925ZShazback
018golflua150516T123114ZKyle Kan
011PHP 11 Bytes150517T063204Zprimo
910TIBASIC150516T192149Zlirtosia
017Python 2150516T165559Zsirperci
004CJam150516T041422ZDennis
018C150516T144453ZAndrea B
004Pyth150516T120051Zmatsjoyc
016Python 2150516T112248ZJames Wi
020Python150516T105545ZTim

AWK, 10 bytes

$0=1-2*/t/

Attempt This Online!

If we can use any output format, this will print 1 for heads, nothing for tails:

6 bytes

$0=/h/

Attempt This Online!

Python 3, 18 bytes

print(i.find("e"))

str.find returns -1 if it can't find the required character. In heads, e is in position 1 (Python is 0-indexed), whereas in tails it doesn't exist.

x86-16 machine code, 8 bytes

As a callable function, input string at DS:SI, output in AL.

80 3C 74    CMP  BYTE PTR[SI], 't'      ; if 'h': CF = 1, if 't': CF = 0 
1A C0       SBB  AL, AL                 ; AL = AL - AL - CF (AL = -CF) 
                                        ;  if 't': AL = 0 and CF = 0
                                        ;  if 'h': AL = -1 and CF = 1 
1C FF       SBB  AL, -1                 ; AL = AL - (-1) - CF 
                                        ;  if 't': AL = AL + 1 = 1
                                        ;  if 'h': AL = AL + 0 = -1
C3          RET

x86-16 machine code, IBM PC DOS, 17 bytes

Or as a standalone DOS COM executable. Input from command line, output to stdout.

00000000: b402 0826 8200 7a04 b22d cd21 b231 cd21  ...&..z..-.!.1.!
00000010: c3

Unassembled:

B4 02           MOV  AH, 02H        ; DOS API display char function     
08 26 0082      OR   DS:[82H], AH   ; set parity flag from input 
7A 04           JPE  HEADS          ; if even, heads - display just '1'
B2 2D           MOV  DL, '-'        ; otherwise first display a '-''
CD 21           INT  21H            ; output DL to console
            HEADS: 
B2 31           MOV  DL, '1'        ; display the '1'
CD 21           INT  21H            ; output DL to console
C3              RET

Explanation:

Use the CPU's parity flag to determine if first char is an 'h' (even number of binary 1's) or a 't' (odd number of binary 1's). This saves one byte over comparing the char in ASCII.

Input/Output:

enter image description here

J, 8 6 bytes

2-2{/:

Same approach as FrownyFrog's APL answer. -2 thanks to Bubbler

Attempt This Online!

2-2{/:
    /:  NB. grade up
  2{    NB. take the third item
2-      NB. subtract from 2

Vyxal, 3 bytes

\eḟ

Try it Online!

Direct translation of the CJam answer (find the index of e, or -1 if not found).

Some more fun ones:

Vyxal, 5 bytes

14βǒ‹

Try it Online!

14β     Convert given string from base 14 to integer
        (invalid digits are treated as -1)
   ǒ    Modulo 3
    ‹   Decrement

Vyxal, 4 bytes

18β±

Try it Online!

18β     Convert from base 18 to integer
   ±    Sign
        "heads" is positive -> 1
        "tails" is negative (because leading digit is invalid) -> -1

JavaScript, 14 bytes

s=>s.search`e`

Try it online!

Vyxal, 8 bytes

`e`c[1|u

Try it Online!

u is -1.

shell (portable/POSIX), 16 bytes

expr $i : he - 1

Try It Online!
Thanks to @StéphaneChazelas in unix.stackexchange.com

Other solutions tried:
echo $[30#$i%7-1] # 17 bytes but only in bash, zsh. Try It Online!
echo $((30#$i%7-1)) # 19 bytes but only bash,ksh,zsh. Try It Online!
he=2;echo $[${i%a*}-1] # 22 bytes But only in bash,zsh . Try It Online!
a=${i%h*};echo ${a:+-}1 # 23 . portable . Try It Online!
he=2;echo $((${i%a*}-1)) # 24 bytes . portable . Try It Online!
IFS=h;set $i;echo ${1:+-}1 # 26 (change IFS) . portable . Try It Online!
(IFS=h;set $i;echo ${1:+-}1) # 28 (subshell) . portable . Try It Online!
(IFS=h;set $i;echo $(($#*2-3))) # 31 bytes . portable . Try It Online!

Note: Using dash as a reasonable simile of a portable shell tester.

R, 58 55 bytes

for(i in scan(,''))print(`if`(utf8ToInt(i)[1]%%8,-1,1))

Try it online!

Really poor attempt, but I the utf8ToInt values for "h","H","t","T" are 104, 72, 116, 84 respectively. As a result, "h" and "H" values are both evenly divisible by 8, while "t" and "T" are not. So a conversion and check for even divisibility yields the desired results.

This method compared to the following method takes different spellings of heads/Heads/HEADS/etc. and tails/Tails/TAILS/etc. As long as it starts with an h/H or t/T it will work properly.

EDIT: -3 bytes switching to a for loop. Prints each value on newline instead of a single array of 1's and -1's.

R, 49 bytes

for(i in scan(,''))print(ifelse(i=="heads",1,-1))

This method was suggested by @user5957401 and is much simpler. The difference here is that this method assumes that the user will input strictly "heads" or "tails" (technically anything but "heads").

Try it online!

C-INTERCAL, 177 bytes

This is my first, and hopefully last, INTERCAL program. INTERCAL is a truly remarkable language. Those who haven't heard of it should immediately investigate (here is the manual I used).

PLEASEDO,1<-#2PLEASEDOWRITEIN,1PLEASEDO.1<-',1SUB#1'~#4DO(2)NEXTDO,1SUB#1<-#76(1)DO,1SUB#2<-#40(2)DO(3)NEXTDO,1<-#1DO,1SUB#1<-#116DOCOMEFROM(1)DOREADOUT,1(3)DOFORGET.1DORESUME#1

The program reads from standard input and writes to standard output. After printing the appropriate string, the program crashes with one of two humorous error messages depending on the input.

Try It Online

Ungolfed

    PLEASE DO ,1 <- #2
    PLEASE DO WRITE IN ,1
    PLEASE DO .1 <- ',1 SUB #1' ~ #4
    DO (2) NEXT
    DO ,1 SUB #1 <- #76
(1) DO ,1 SUB #2 <- #40
(2) DO (3) NEXT
    DO ,1 <- #1
    DO ,1 SUB #1 <- #116
    DO COME FROM (1)
    DO READ OUT ,1
(3) DO FORGET .1
    DO RESUME #1

Well, that didn't help much...

In the first three lines, we read 2 (#2 in INTERCAL) characters from the input into array ,1 and store in variable .1 whether the first character read has bit 2 set (mask of 4); in ASCII h is 0b1101000 and t is 0b1110100, so this variable now indicates whether the input is tails. This uses the "select" operator ~, which in this case performs both masking and shifting to select bit 2 as 0 or 1.

The rest of the program is an if/else conditional and a print statement. Unfortunately, control flow is very limited in INTERCAL. The only mechanism is a call stack that's pushed to when the program executes DO (x) NEXT. DO RESUME #1 then operates like a return statement (but with no return value), popping the stack and jumping to the next statement after the most recent DO (x) NEXT. But the value passed to DO RESUME can be any number. DO RESUME #3 pops the call stack three times and jumps to the third-from-last DO NEXT.

A similar construct is DO FORGET, which only pops the stack the specified number of times but does not jump. DO RESUME always jumps, so passing it 0 is a run-time error. But the instruction DO FORGET #0 is valid, and doesn't do anything.

And so with the statements DO (2) NEXT and DO (3) NEXT I push two locations onto the call stack. At (3) I then discard .1 frames, which has the effect of "forgetting" the call at (2) if and only if the input was tails. As a result, we end up just after either DO (2) NEXT or DO (3) NEXT after the return on the last line, depending on the input.

Each branch then loads the appropriate character data into ,1 (see here for why the values don't make any sense), and COME FROM (1), an inverted goto, joins the two branches at the output statement DO READ OUT. Control then continues, but luckily in either case the program crashes before printing anything else.

Runic Enchantments, 10 bytes

1i3%1C=?Z@

Try it online! (heads)
Try it online! (tails)

Works by determining if the 4th character is a d (compare to number literal 100) and if not, multiplies a 1 by -1, then prints and terminates.

1              Push 1 (the output)
  i            Read input string
   3%          Get 4th character (0-indexed)
     1C=?      Compare with 100 (decimal value of d)
         Z     If false, multiply TOS with -1
          @    Output entire stack (the only thing left with be a 1 or -1) and terminate

Brain-Flak, 52 34 bytes

({}[{}()()()])({<{{}}>[()()]}()<>)

Output is the top element of the stack

-18 bytes thanks to Jo King

Try it with heads!

Try it with tails!

JavaScript (V8) - 19 Bytes

Since OPs solution returns 'true' and '-1' (see here), the following function:

f=i=>i[0]=='h'?1:-1

returns '1' and '-1' - see here. Just to be a smart-ass and so.

// Adaption of Java (SDK) version as a JS function.

Java (JDK), 18 bytes

i->i=="heads"?1:-1

Try it online!

MathGolf, 3 bytes

'e=

Try it online!

Basically identical to a lot of other solutions. Checks the index of 'e', and returns -1 if not found.

Zsh, 13 12 bytes

-1 from @Isaac

<<<$[#1%7-5]

Try it online! Try it online!

man zshmisc, under Arithmetic Evaluation:

An expression of the form ##x where x is any character sequence such as a, ^A, or \M-\C-x gives the value of this character and an expression of the form #name gives the value of the first character of the contents of the parameter name.

Keg, 8 12 8 bytes

_d=2*1-.

Try it online!

Explanation (syntactically invalid)

_        Take input and discard the last item
 d=      If the top of the stack is d:
   2*    Re-set the top of the stack as 2
     1-  Decrement the top of the stack by 1
       . Explicitly output the top of the stack

-4 bytes thanks to manatwork

brainfuck, 42 bytes

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

Try it online!

Checks if it is heads or tails by checking if the ordinal values of first two characters are only three away from each other.

ed, 27 25 21 bytes

ed gave me a headache. Finally figured it out with help from @ed1conf on twitter and some peeps on unix.se. You can't just match things with s/re/newtext/, you have to prefix it with g otherwise ed packs a sad. It's like a grumpy 50 year old unix program saying "get off my lawn".

g/t/s//-
,s/\w\+/1
w

Try it online!

-2 bytes by dropping the final /s
-4 bytes thanks to @manatwork (& whose sed answer i plagiarised)
Old version:
g/t/s//- g/\w\+/s//1 wq .

><>, 9 bytes

ab*i-6,n;

Try it online!

I'm honestly surprised that there wasn't a fish answer yet.

Subtracts the ASCII value of the first character input from 110 and divides by 6.

jq, 14 characters

index("e")//-1

That's searching character position in the string. Unfortunately on not found it returns null, so the // (alternative operator) has to be used. (Still shorter than an .[:1]<"i" check as that results boolean and there is no way to cast that to integer.)

Sample run:

bash-5.0$ jq -R 'index("e")//-1' <<< 'heads'
1

bash-5.0$ jq -R 'index("e")//-1' <<< 'tails'
-1

Try it online!

Gema, 7 characters

t=-
*=1

Generally the same thing as my Sed solution does, but there is a big difference: Sed executes all commands on the pattern space (so later commands act on previous command's result), while Gema handles each piece of input once and discards it.

So although in the 1st step Gema's t=- does the same as Sed's s/t/-/, in the 2nd step Gema's *=1 will act either on “ails” or “heads”, while Sed's s/\w\+/1/ has to handle either “-ails” or “heads”.

Sample run:

bash-5.0$ gema 't=-;*=1' <<< 'heads'
1

bash-5.0$ gema 't=-;*=1' <<< 'tails'
-1

Try it online!

Zsh, 25 19 bytes

-5 bytes using @Digital Trauma's bash solution; get the second letter, either e or a. Then 0xe and 0xa are interpreted as hex, i.e. decimal 14 and 10. Then we do a bit of arithmetic to output 1 or -1.

Try it Online!

<<<$[0x${1[2]}/2-6]

24 bytes: <<<${1[1]:s/h//:s/t/-/}1

25 bytes: <<<${1[1]:s/h/1/:s/t/-1/}

Triangular, 10 bytes

F.~%.7/-_<

Try it online!

Divides the ASCII value of a character input by 7. Subtracts the quotient from 15. Execution stops when the IP runs out of the program space. This works because Triangular can only manage integer division. Conveniently, "h" has a value of 104, which is 14 when integer divided by 7; "t" is 116, which is 16 when integer divided by 7.

Ungolfed/Explanation:

   F
  . ~
 % . 7
/ - _ <
---------------------------------------------------------------
F                 - Push 15 to Top of Stack
 ~                - Read a character from input, push its value to ToS
   7              - Push 7 to ToS
     <_           - Change directions, then pop ToS-1 and ToS, push their integer quotient
        -         - Pop ToS-1 and ToS, push their difference
          %       - Print ToS as an integer

Previous version (14 bytes):

~\81|m/,!<.>i%

Read a character from input; if that character's ASCII value divided by 8 has a remainder, print -1, otherwise print 1.

Bash, 22

echo $[0x${1:1:1}/2-6]

Takes the 2nd letter (e or a) and interprets it as a hex digit (14 or 10), then divide by 2 and subtract 6 to get the right answers.

Try it online!

dc, 8 bytes

?z2*1r-p

dc can't do anything meaningful with strings other than read them in and attempt to evaluate them. Doing this, "heads" outputs some warnings about unimplemented commands and empty stack, which we ignore, but importantly the stack remains empty. "tails" does almost the same with the important exception that the final "ls" loads a value from the s register to the stack.

We then use "z" to get the stack length and arithmetically fiddle to get the right answers.

Try it online!

PowerShell, 15 bytes

($args[1]-99)/2

Try it online!

Takes input via splatting. Uses the e vs the a to do ASCII math

Gaia, 5 4 bytes

'eI(

Similar to Dennis' CJam answer, finds the index of e in the input string

Saved one byte since I didn't realise input was automatically used as an argument if there isn't enough stack values

How it works

'e  Push e
I   Index of e in the the input. 2 if heads, 0 if tails
(   Subtract One
Stack gets automatically outputted

Try it Online!

Commodore BASIC (PET, VIC-20, C64/128, C16/+4, TheC64Mini) 44 Tokenized and BASIC bytes

 0b$="heads":inputa$:?-1*(b$=a$)+1*(a$<>b$)

Commodore BASIC returns -1 as TRUE and 0 as FALSE, so a bit of simple maths is required to output the right required answer here.

Commodore VIC-20 Heads or Tails

33, 12 bytes

P110mz6dzcmo

Try it online!

Requires heads or tails non-capitalised.

This only accepts the first character of the input. If it needs to accept all input, replace the P with Ij.

Explanation

P            | Get the first character of input as its ASCII value
             |              ( h | t )
 110mz       | Subtract 110 (-6 | 6 )
      6dz    | Divide by 6  (-1 | 1 )
         cm  | Flip sign    ( 1 |-1 )
           o | Print it

Whitespace, 40 bytes

[S S S N
_Push_0][S N
S _Duplicate_0][T   N
T   S _Read_input_as_character][T   T   T   _Retrieve][S S S T  T   T   N
_Push_7][T  S T T   _Modulo][S S S T    S T N
_Push_5][T  S S T   _Subtract][T    N
S T _Print_as_integer]

Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.

Since Whitespace inputs one character at a time, I use that to my advantage here by only looking at the first character and porting @recursive's Stax answer (so make sure to upvote him as well!)

Try it online (with raw spaces, tabs and new-lines only).

Explanation in pseudo-code:

Integer c = STDIN as character code-point
c = c % 7
c = c - 5
Print c to STDOUT as integer

05AB1E, 3 bytes

'ek

Try it online or verify both test cases.

Explanation:

'ek '# Get the 0-based index of "e" in the (implicit) input-string
     # (or -1 if no "e" is present)
     # (and output the result implicitly)

@, 16 bytes

I will expand it later.

?-ň*8+94{1}{-1}

Explanation

?               If statement
 -ň             Subtract input with
   *8+94        The ASCII code of h
        {1}     If true, return 1
           {-1} Otherwise, return -1

Stax, 4 bytes

└0Y.

Run and debug it

It's the codepoint of the first character mod 7 minus 5.

Perl 5 -p, 10 bytes

$_=o cmp$_

Try it online!

Stax, 3 bytes

'eI

Run and debug it

Japt, 2 bytes

ae

Try it online

APL (Dyalog Unicode), 5 bytes

3-3⊃⍋

Try it online!

Homespring, 50 bytes

youth. fountain bear 1 pump heads    -1 pump tails

very simple, make the input salmon young, block him after he enters the right branch so he spawns early, then bear eats the downstream input salmon

SmileBASIC, 15 bytes

H=2?VAR(I[T])-1

Not the shortest possible solution, but I didn't want to post a boring program that's the same as all the others.

The VAR "function" converts a variable name into a variable. VAR("X") = 1 is equivalent to X = 1, for example.

The program sets H to 2, then uses VAR() on the first character in the input string.
(I[T] is the same as I[0], because T is 0. I had to include T here because VAR is not allowed to create new variables).

If the input is heads, VAR() returns the variable H, which has a value of 2.
If the input is tails, VAR() returns the variable T, which has a value of 0.

Then, it subtracts 1 from this and outputs either -1 or 1.

Because variable names in SmileBASIC are not case sensitive, this program works for any capitalization of the input string.

Note:
Normally, string variables must have names ending in $, but there are several ways to avoid this restriction. The simplest is to put the code inside a function, because function arguments are not type checked:

TEST "heads"
TEST "tails"

DEF TEST I
 H=2?VAR(I[T])-1
END

Vitsy, 13 bytes

So what, I'm late for the party. ¯\_(ツ)_/¯

zv&v'h'=)i1rN
z             Grab all input.
 v            Capture the top item (h or t) as a temp variable.
  &           Generate new stack, move to it.
   v'h'=      Test if the variable is h.
        )i    If it isn't, push -1.
          1   Push 1.
           r  Reverse the stack.
            N Print out the top item as a number.

Unefunge 98, 15 or 16 bytes

'h-4j@.-1_1.@

The above code assumes input is stored on top os the stack in reverse order. There are two 16-byte solutions that don't make this assumption:

$'d-4j@.-1_1.@

Assuming input is on top of the stack in normal order.

~'h-4j@.-1_1.@

Reading input from stdin

QBasic, 11 bytes

This has got to be the shortest piece of QBasic I've ever written.

c=i>"t
?c^c

Explanation:

The above is some pretty heavily golfed QBasic. Once the autoformatter gets through with it, it'll look like this:

c = i > "t"
PRINT c ^ c

The first line compares the string i with "t". If i is "heads", i > "t" is false and c = 0. If i is "tails", i > "t" is true and c = -1. Yes, -1 is the default value for boolean true in QBasic!

The second line maps -1 to -1 and 0 to 1 via a math trick: (-1)^(-1) == 1/(-1) == -1, and 0^0, though technically mathematically undefined, returns 1.

This code requires that i be explicitly declared as a string variable; otherwise, it would have to be i$. Full test program (tested on QB64):

DIM i AS STRING
DATA heads, tails

FOR x = 1 TO 2
READ i

c=i>"t
?c^c

NEXT x

Fission, 26 21 Bytes

O/';'1
"S@]_"-
R? <tL

Martin (and his excellent answer here) convinced me to learn a new language, and what better place than a quick golf? This is almost certainly not optimal, but hey, it was fun! Once I feel good about it, I may provide some form of explanation if it is requested.

Tr: 17 13 characters

(Or 14 10 if you count only the arguments…)

tr -s ta-s -1

Sample run:

bash-4.3$ tr -s ta-s -1 <<< heads
1

bash-4.3$ tr -s ta-s -1 <<< tails
-1

Brief explanation:

tr stands for transliterate, that means, replaces each character of the input found in the first argument with character at the same position in the second argument:

tr ta -1 <<< tails         # replaces t ⇢ -, a → 1
⇒ -1ils

If the first argument is longer, the characters without positional match in the second argument are replaced with second argument's last character:

tr tals -1 <<< tails       # replaces t ⇢ -, a → 1, l → 1, s → 1
⇒ -1i11

When -s (--squeeze-repeats) option is used, successive characters which would be replaced with the same character are replaced at once:

tr -s tals -1 <<< tails    # replaces t ⇢ -, a → 1, l+s → 1
⇒ -1i1

So if we enumerate all characters in “tails”, we get what we need:

tr -s tails -1 <<< tails    # replaces t ⇢ -, a+i+l+s → 1
⇒ -1

Same for “heads”, but wee need to keep the “t” in front to consume the minus (characters sorted alphabetically for creepiness):

tr -s taedhs -1 <<< heads   # replaces h+e+a+d+s → 1
⇒ 1

Merging all uniques characters of “tails” and “heads” in a single first argument, keeping “t” in front leads to final solution:

tr -s tadehils -1 <<< tails # replaces t → -, a+i+l+s → 1
⇒ -1

tr -s tadehils -1 <<< heads # replaces h+e+a+d+s → 1
⇒ 1

To avoid enumerating the characters, an interval in from-to format can be used instead.

Sed: 16 characters

s/t/-/
s/\w\+/1/

Sample run:

bash-4.3$ sed 's/t/-/;s/\w\+/1/' <<< 'heads'
1

bash-4.3$ sed 's/t/-/;s/\w\+/1/' <<< 'tails'
-1

C, 22 bytes

puts(*i>'h'?"-1":"1");

Credits goes to @TheE for telling me about this!

Explanation:

If the first character of the string is greater than 'h', the string "-1" is printed. Otherwise, the string "1" gets printed. Note that this approach comes with a trailing newline character.


Old version (25 bytes):

printf("%d",*i>'h'?-1:1);

Explanation:

If the first character of the string is greater than 'h', -1 is printed. Otherwise, 1 is printed.

Befunge, 28 bytes

28 bytes including whitespace and newlines:

<v"heads"
 >94+%v
,,"-1"_1.@

Assumes that either heads or tails is put into the string above (this is the equivalent of assuming the input is stored in i). Works by performing modulo 13 on the top character on the stack - h divides exactly, t does not.

I also made a 22 character version (excluding whitespace/newlines) but the input has to be backwards:

"sdaeh"v
       9
       4
       +
       %
@,,"-1"_1.

Ruby, 8 (6 without output)

p ?t<=>i

Rocketship operator!

Haskell, 18 bytes

f('h':_)=1
f _= -1

Every string starting with the letter h is mapped to 1, all others to -1.

VBA (Excel), 12 bytes

Not a fantastic bit of golfing, but it's fun to try with VBA to get anywhere near to a proper programming language...

?13-asc(i)/6

i is the string, and it just exploits the ASCII value of the first character, divided by 6 and substracted from 13 to give 1 or -1. Very simple.

Example run in immediate window (10 extra bytes to set the input variable) :

i="Heads":?13-asc(i)/6
 1

golflua 25 20 18

w(I.r():f'h'&1|-1)

Probably could be golfed some more by using some tricks that I'm not thinking about at the moment. (see history for old version) Saved 5 chars by moving input to write and ignoring the if statement there. Two more chars were saved by ignoring the optional parenthesis on find. It does not check for failed conditions (i.e., input that isn't heads or tails).

A Lua equivalent would be

io.write(io.read():find('h') and 1 or -1)

PHP - 11 Bytes

<?=1-$i^=F;

This works because 'tails' ^ 'F''2' and 'heads' ^ 'F''.', which when typed as an integer is 0.

You may test this solution (or any of the below) in the following way:

<?php foreach(['heads', 'tails'] as $i): ?>
 <?=1-$i^=F;
endforeach; ?>

Ideone Link


Alternatives

15: <?=1-md5($i)%3;
16: <?=md5($i)[5]-5;
16: <?=-crc32($i)%5;

TI-BASIC, 9-10 bytes

cos(πʳinString(Ans,"t

Straightforward. "t" is in position 1 of "tails", but "t" is not in the string "heads", so inString( returns 1 for tails and 0 for heads.

If your calculator is in radian mode (as any mathematician's should be), it takes only nine bytes:

cos(πinString(Ans,"t

Note that TI calculators do not have named strings, so the input is in the calculator's answer variable. Also note that lowercase letters are two bytes each, so this solution actually takes less memory than than the word "heads".

Python 2, 17 bytes

print'-1'['t'>i:]

'heads' is less than 't', so it evaluates to True == 1, and prints the string after the first character. 'tails' is greater than 't', so it evaluates to False == 0 and the whole string is printed.

If we're doing this from the command line, with implicit printing, it just becomes:

'-1'['t'>i:]

...for 12 bytes, but it adds single quotes to the output.

CJam, 4 bytes

I'e#

Assumes that the variable I holds the input, since i isn't a valid identifier in CJam.

Try it online.

This is equivalent to the JavaScript code I.indexOf('e').

C, 18 bytes

Pretty easy, but let's do it just for fun...

puts("-1"+*i/8%2);

Given the string char *i it prints 1 for heads and -1 for tails, with trailing newline.

Explanation

In C, "-1" + 1 points to 1 character forward, so it is the same as "1". Let's take a look at the first characters:

"heads"[0] = 'h' = 104 = 0b01101000
"tails"[0] = 't' = 116 = 0b01110100

If we count the bits from the rightmost one starting at zero, bit 3 is 1 in heads and 0 in tails: summing it to "-1" gives the right string. It looks like this:

"-1" + ((i[0] >> 3) & 1)

Now, substitute i[0] with *i and the right shift with the power-of-two division to save some bytes. Also remove useless parentheses:

"-1" + (*i / 8 & 1)

Now, & 1 can be substituted with % 2. The character count is the same, but the modulus has higher priority, allowing to drop the parentheses. Remove the whitespace:

"-1"+*i/8%2

Bonus

I think the shortest way to get an integer 1 or -1 (not a string) in C is:

18-*i/6

Explanation:

'h' = 104
't' = 116

('h' + 't') / 2 = 110
110 - 'h' =  6
110 - 't' = -6

(110 - 'h') / 6 =  1
(110 - 't') / 6 = -1

Apply distributive property (integer division):
18 - 'h' / 6 =  1
18 - 't' / 6 = -1

Pyth - 4 bytes


 xz"e

Run with heads or tails. As i is int in Pyth, this uses z as the variable name, which contains any user input. It is equivalent to the Python print(z.find("e")), so uses @Dennis's method.

Python 2, 16 bytes

print(i<'t')*2-1

Python, 20 bytes

print(('h'in i)*2-1)

This returns False if it isn't, and True if it is. In python False and 0 are the same, and True and 1 are as well.

So:

True (1) * 2 -1 = 2-1 = 1
False (0) * 2 - 1 = 0-1 = -1