15
\$\begingroup\$

This question already has an answer here:

The puzzle is as follows:

Create the traditional 'Guess my Number' game in as little keystrokes as possible. The player should input a guess between and including 1 and 100, and the computer should reply with either + (meaning the player needs to guess higher), - (meaning the player needs to guess lower) or = (meaning the player has guessed the number. The game continues until the player has guessed the number. The number that the computer generates MUST be a random number between and including 1 and 100.

Sample gameplay

50
+
75
-
60
-
55
+
57
=

Happy Golfing!

\$\endgroup\$

marked as duplicate by Howard, Peter Taylor, zzzzBov, Toto, Kevin Brown Apr 17 '13 at 16:27

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • \$\begingroup\$ Whoever can post an answer fastest with the OSK in most OSes gets my vote. That's like, 3 keystrokes to open \$\endgroup\$ – Bojangles Apr 11 '13 at 15:21
  • \$\begingroup\$ @Howard this one is basically a simplified version of the one you found. Not an exact duplicate, though \$\endgroup\$ – John Dvorak Apr 11 '13 at 15:41
  • \$\begingroup\$ @JanDvorak, I feel its not a significant enough variant to warrant a different question. \$\endgroup\$ – zzzzBov Apr 11 '13 at 20:30
  • \$\begingroup\$ @zzzzBov how does that work on a puzzle site, this is a slightly different question though I agree it's pretty close. However the other one has an accepted answer. what if people want to work this puzzle but not the other one? \$\endgroup\$ – Ryan Apr 11 '13 at 22:31
  • \$\begingroup\$ @ryan, I don't know how it works on a site such as Code Golf. I fully understand the predicament of posing a challenge similar to an existing one, however in this case, I feel that this one is too similar to the existing one. It's an opinion, and in the end the votes are what will decide whether or not this gets closed or stays open. \$\endgroup\$ – zzzzBov Apr 11 '13 at 22:34

24 Answers 24

10
\$\begingroup\$

Ruby: 63 58 52 49 characters

puts"=-+"[r=$_.to_i<=>n||=1+rand(100)];r==0&&exit

Sample run:

bash-4.2$ ruby -ne 'puts"=-+"[r=$_.to_i<=>n||=1+rand(100)];r==0&&exit'
50
-
25
+
37
+
43
-
40
+
42
=
\$\endgroup\$
  • 2
    \$\begingroup\$ A few small improvements: exit if r==0 -> r==0&&exit, and there is no whitespace needed in puts"=-+". \$\endgroup\$ – primo Apr 11 '13 at 19:04
  • \$\begingroup\$ I remembered the && trick just this morning. Seems I'm getting slow. \$\endgroup\$ – manatwork Apr 12 '13 at 7:21
  • \$\begingroup\$ Ups, sorry. I read the code wrong. \$\endgroup\$ – Howard Apr 12 '13 at 10:50
  • \$\begingroup\$ Is 1+$$%100 random enough? \$\endgroup\$ – Howard Apr 12 '13 at 10:59
  • \$\begingroup\$ +1 for 42 as a random number :) \$\endgroup\$ – tomsmeding Apr 14 '13 at 17:31
9
\$\begingroup\$

Python 84 83 characters

import os
a,c=0,ord(os.urandom(1))%100+1
while c-a:a=input();print'=-+'[c!=a:][c>a]
\$\endgroup\$
6
\$\begingroup\$

JavaScript, 52

for(u=r=1+new Date%100;u=r-prompt(u<0?'-':'+'););'='

Just paste it in the console.

\$\endgroup\$
  • \$\begingroup\$ Nice one! Even if skips some of the rules: uses 0..99 interval instead of 1..100 and not displays “=” on success. \$\endgroup\$ – manatwork Apr 11 '13 at 17:39
  • \$\begingroup\$ @manatwork now I guess I can read the rules :) I edited for the 1..100. \$\endgroup\$ – Denys Séguret Apr 11 '13 at 17:41
  • \$\begingroup\$ @manatwork I edited for the = too. Much less elegant. I'll try later to make it shorter. \$\endgroup\$ – Denys Séguret Apr 11 '13 at 17:44
  • \$\begingroup\$ You can save 1 character by using a reference to prompt(): first p=prompt, then just p(). But something is wrong with the logic, as the “=” only appears if you guess the number on first try. \$\endgroup\$ – manatwork Apr 11 '13 at 17:50
  • \$\begingroup\$ I must leave for a moment. But this version should work (less user friendly, though). \$\endgroup\$ – Denys Séguret Apr 11 '13 at 17:59
6
\$\begingroup\$

Perl 57 53 50 (thanks to @manatwork) Characters

$_=qw(= + -)[$^T%100+1<=>$_];print"$_
";exit if/=/

Note You need to invoke with -n option

Alternate version as suggested by @primo

Perl 40 Characters

$_=chr 44-($^T%100+1<=>$_||exit print'=')
\$\endgroup\$
  • 1
    \$\begingroup\$ qw(= - +) is shorter than ('=','-','+') \$\endgroup\$ – manatwork Apr 11 '13 at 17:02
  • \$\begingroup\$ @manatwork: I am not a perl expert. Thank you for the advise :-) \$\endgroup\$ – Abhijit Apr 11 '13 at 17:03
  • \$\begingroup\$ You not need while, if is enough. And please change the response logic. \$\endgroup\$ – manatwork Apr 11 '13 at 17:05
  • \$\begingroup\$ @manatwork: I think you can use this answer to post a new one (you deserve it). Once you are done, I will delete it. As I said am not an expert of Perl :-) \$\endgroup\$ – Abhijit Apr 11 '13 at 17:09
  • 2
    \$\begingroup\$ Bit of a re-work, but essentially the same for 41 (actually 40, because ^T can be replaced with character 20), requires -pl: $_=chr 44-($^T%100+1<=>$_||exit print'=') \$\endgroup\$ – primo Apr 11 '13 at 18:25
5
\$\begingroup\$

APL (28)

{'='≠⎕←'+=-'[2+×⎕-⍵]:∇⍵}?100
\$\endgroup\$
  • 3
    \$\begingroup\$ I can't read this, but it looks cool. \$\endgroup\$ – asteri Apr 12 '13 at 15:57
3
\$\begingroup\$

Haskell, 128

Won’t be winning any awards, but here it is.

main=fix.(.)(=<<(read<$>getLine)).f=<<(`mod`100).fst.next<$>newStdGen where p=putStrLn;f y r x|x<y=p"+">>r|x>y=p"-">>r|True=p"="

Ungolfed logic and imports:

import Control.Applicative
import Data.Function
import System.Random

main :: IO ()
main = do
  random <- newStdGen
  let number = fst (next random) `mod` 100
  fix $ \loop -> do
    guess <- read <$> getLine
    check number guess loop
  where
    check number guess loop
      | guess < number = do
        putStrLn "+"
        loop
      | guess > number = do
        putStrLn "-"
        loop
      | otherwise = putStrLn "="
\$\endgroup\$
3
\$\begingroup\$

C#: 147 136 Characters

It won't beat most other languages, but here's a C# solution for fun:

var r=new Random().Next(1,100);var g=0;while(g!=r){g=int.Parse(Console.ReadLine());Console.WriteLine(""+g+'\n'+(g<r?'+':g>r?'-':'='));}
\$\endgroup\$
  • \$\begingroup\$ Is that a complete C# program source ? \$\endgroup\$ – Denys Séguret Apr 11 '13 at 20:15
  • \$\begingroup\$ I remember seeing a post on meta about ignoring standard overhead/bloat from languages like C#/Java (can't find the link now). It will copy-paste into LINQPad. \$\endgroup\$ – Anthony Apr 12 '13 at 10:23
  • \$\begingroup\$ If you remove overhead from other, they'll be shorter too. The Go one for example could be reduced to 105 chars. But it would be hard to define a unique line, so I don't think that really makes sense. \$\endgroup\$ – Denys Séguret Apr 12 '13 at 10:25
  • 1
    \$\begingroup\$ You can trim another 27 by changing your definition, loop handling, and unnecessary echo of the input. int r=new Random().Next(1,100),g=0;while(g!=r){g=int.Parse(Console.ReadLine());Console.WriteLine(g<r?'+':g>r?'-':'=');} \$\endgroup\$ – GalacticCowboy Apr 12 '13 at 19:22
  • \$\begingroup\$ Your code will never choose the number "100", it should be Next(1,101) or Next(100)+1. :) \$\endgroup\$ – thepirat000 Aug 10 '13 at 6:05
2
\$\begingroup\$

Clojure (117 characters)

java -jar clojure.jar  -e "(loop[n(int(*(rand 100)))]((get{-1#(prn '+)0#(do(prn '=)(System/exit 0))1#(prn '-)}(compare(eval(read))n)))(recur n))"
50
+
75
+
90
-
86
-
82
=

Clojure (74 characters)

Guessing a real number. Nobody will be patient enought to solve to "=", so nobody notice the missing exit.

java -jar clojure.jar  -e "(loop[n(rand)](prn (get{-1 '+ 0 '= 1 '-}(compare(eval(read))n)))(recur n))"
0.5
+
0.8
-
0.6
+
0.7
+
0.75
-
0.72
+
0.74
+
0.745
+
0.748
-
0.746
-
0.7455
-
...
\$\endgroup\$
2
\$\begingroup\$

R, 89 85 chars

s=sample(1:100,1);while(s!=(a=as.real(readline())))cat(ifelse(a>s,"-","+"));cat("=")
\$\endgroup\$
  • 1
    \$\begingroup\$ +1 putting the user guess in the while condition is indeed a good idea! However defining cat as a variable here actually cost you 2 characters: w=cat; (6) + 2 times w are 8 characters while 2 times cat is only 6 characters! :) I think you can also get rid of the curly braces since your while loop now contains only 1 line. \$\endgroup\$ – plannapus Apr 12 '13 at 13:57
  • \$\begingroup\$ @plannapus Good points! The w= made a lot more sense when I was using write, but your way is better. \$\endgroup\$ – eykanal Apr 12 '13 at 14:49
2
\$\begingroup\$

C89 92 90 89 (Thanks to @ugoren) 84 characters running on OS and linked with Linker supporting ASLR

main(c,g){g=g/8%100+1;while(scanf("%d",&c)&&printf("%c\n",g-c?"-+"[c<g]:'=')&&c-g);}
\$\endgroup\$
  • \$\begingroup\$ I don't think that will produce very random numbers in many OSes, unless address space randomization is turned on. \$\endgroup\$ – fluffy Apr 11 '13 at 21:05
  • \$\begingroup\$ @fluffy: I already mentioned in my most. And IMHO, all modern OSes except RTOS supports ASLR \$\endgroup\$ – Abhijit Apr 12 '13 at 2:46
  • \$\begingroup\$ main(c,g) would save int. Or maybe main(g,c), assuming the argument vector is randomized by ASLR. \$\endgroup\$ – ugoren Apr 12 '13 at 10:14
  • \$\begingroup\$ However, ASLR will not randomize the low bits.The address of main will always be a multiple of 4 (at least). \$\endgroup\$ – ugoren Apr 12 '13 at 10:15
  • \$\begingroup\$ @ugoren: Yes I agree and so changed my code accordingly. On another context I have not acceoted your edit, cause the particular bahaviour of missing type defaulting to int is not accepted in C99. \$\endgroup\$ – Abhijit Apr 12 '13 at 10:55
1
\$\begingroup\$

K, 69

b:1b;g:1+*1?100;while[b;-1(*$[g<f:"I"$m:0:0;"-";g>f;"+";("=";b:0b)])]

Could definitely be golfed more

k)b:1b;g:1+*1?100;while[b;-1(*$[g<f:"I"$m:0:0;"-";g>f;"+";("=";b:0b)])]
50
+
75
-
60
+
65
-
63
+
64
=
\$\endgroup\$
1
\$\begingroup\$

Go, 152

Golfed :

package main
import(f"fmt";"os")
func main(){
c:=1+os.Getpid()%100
u:=0
for u!=c{
f.Scanf("%d",&u)
s:="="
if u<c{s="+"}else if u>c{s="-"}
f.Println(s)}}

Ungolfed :

package main

import (
    f "fmt"
    "os"
)

func main() {
    c := 1 + os.Getpid()%100
    u := 0
    for u != c {
        f.Scanf("%d", &u)
        s := "="
        if u < c {
            s = "+"
        } else if u > c {
            s = "-"
        }
        f.Println(s)
    }
}

Session :

guess

4

+

88

-

66

+

77

-

71

+

73

+

75

=

Hard to golf when you start any program with package main and a list of imports...

\$\endgroup\$
  • 2
    \$\begingroup\$ But real golf has big bags full of heavy clubs. There are even wheels on the bags. What's more they are "imported" for you by your caddy. And you drive around a big, reserved field in electric carts. Let's not even speak about the annual fee. \$\endgroup\$ – Kaz Apr 12 '13 at 3:13
1
\$\begingroup\$

R: 88 characters

r=sample(1:100,1);i=scan(n=1);while(i!=r){cat(ifelse(i<r,"+","-"));i=scan(n=1)};cat("=")

Ex:

> r=sample(1:100,1);i=scan(n=1);while(i!=r){cat(ifelse(i<r,"+","-"));i=scan(n=1)};cat("=")
1: 23
Read 1 item
+
1: 46
Read 1 item
-
1: 35
Read 1 item
-
1: 31
Read 1 item
-
1: 28
Read 1 item
+
1: 30
Read 1 item
-
1: 29
Read 1 item
=
>
\$\endgroup\$
  • \$\begingroup\$ Look at my answer; this can be shortened by (1) defining a cat variable and (2) defining i in the while loop. You can also use the quiet option to remove the "Read 1 item" notice, but I don't think you can turn off scan's "1:" prompt. \$\endgroup\$ – eykanal Apr 12 '13 at 12:40
1
\$\begingroup\$

PHP: 95 91 87 73 71 65 chars

<?php $n=rand(1,100);while(@$g!=$n){$g=trim(fgets(STDIN));echo$g==$n?'=':($g>$n?'-':'+')."\n";}
<? for($n=rand(1,100);@$g!=$n?$g=trim(fgets(STDIN)):0;)echo$g==$n?'=':($g>$n?'-':'+')."\n";
<? for($n=rand(1,100);$n!=$g=trim(fgets(STDIN));print(($g>$n?'-':'+')."\n"));echo"=\n";
<? for($n=rand(1,100);$n!=$g=fgets(STDIN);print(($g>$n?'-':'+')."\n"))?>=
<? for($n=rand(1,100);$n!=$g=fgets(STDIN);print($g>$n?'-':'+')."\n")?>=
<?for($n=rand(1,100);$n!=$g=fgets(STDIN);print$g>$n?"-
":"+
")?>=
\$\endgroup\$
  • 1
    \$\begingroup\$ 89: <? for($n=rand(1,100);($g=trim(fgets(STDIN)))!=$n;print$g==$n?'=':($g>$n?'-':'+')."\n"); \$\endgroup\$ – Taylor Fausak Apr 12 '13 at 20:17
  • \$\begingroup\$ You don't need to call trim, since 8 == "8\n". That brings it down to 81 characters: <? for($n=rand(1,100);$n!=$g=fgets(STDIN);print(($g>$n?'-':'+')."\n"));echo"=\n"; \$\endgroup\$ – Taylor Fausak Apr 12 '13 at 20:57
  • \$\begingroup\$ You can get it down to 73 characters by exiting PHP mode at the end instead of calling echo: <? for($n=rand(1,100);$n!=$g=fgets(STDIN);print(($g>$n?'-':'+')."\n"))?>= \$\endgroup\$ – Taylor Fausak Apr 12 '13 at 21:51
1
\$\begingroup\$

C: 86 characters

i;main(r){r+=(7*time(0)+3)%100;while(scanf("%d",&i)&&puts(i<r?"+":i>r?"-":"=")&&i-r);}

It is well-behaved, implements a simple LCG and compiles under both Clang (Clang is much more picky than GCC) and GCC.

\$\endgroup\$
1
\$\begingroup\$

R 70

n=sample(1e2)[1];while(n-(g=scan(n=1)))cat(if(n>g)"+"else"-");cat("=")
\$\endgroup\$
1
\$\begingroup\$

VB.net 146

Dim r,g As Integer:Dim s As String:r=New Random().Next(1,100):Do Until g=r:g=InputBox(s):If g<r Then s="+" Else If r=g Then s="-" Else s="=" Loop

\$\endgroup\$
  • \$\begingroup\$ Your code will never choose the number "100", it should be Next(1,101) \$\endgroup\$ – thepirat000 Aug 10 '13 at 6:18
1
\$\begingroup\$

Tcl, 96 chars

set n [expr int(rand()*100)+1];while {[gets stdin g]&&$g!=$n} {puts [expr $g<$n?"+":"-"]};puts =

Ok, and now guessing a real number (91 chars):

set n [expr rand()*100+1];while {[gets stdin g]&&$g!=$n} {puts [expr $g<$n?"+":"-"]};puts =

And here a small script to test this: (Solver)

set fd [open "| /usr/local/bin/tclsh hilo.tcl" RDWR]
fconfigure $fd -buffering none
lassign 0\ 100 + -
while 1 {
    puts "-> [set new [expr {(${-} - ${+}) / 2. + ${+}}]]"
    puts $fd $new
    gets $fd in
    puts "<- $in"
    if {$in in {+ -}} {set $in $new} break
}

Change the 2. to 2 for integers.

\$\endgroup\$
0
\$\begingroup\$

Javascript (75 74 chars):

for(n=1+Math.random(a=alert)*100>>0;(g=+prompt())-n;)a('+-'[+(g>n)]);a('=') 
for(n=1+Math.random(a=alert)*100>>0;(g=+prompt())-n;)a(n>g?'+':'-');a('=')

Numbers are actually random

\$\endgroup\$
0
\$\begingroup\$

J: 64 characters

r=.>:?100
while.(t=.{&'<=>'>:*-&r".(1!:1)1)~:'='do.t(1!:2)2 end.t

Doing I/O in J is sort of bulky compared to the rest of the language.

\$\endgroup\$
0
\$\begingroup\$

vbScript 115 110

Randomize:dim n,r,s:r=(Int)((100*Rnd+1)*2):do until(r=n*2):n=inputbox(s):If(n*2>r)Then:s="-":else:s="+":end if:loop

Randomize:dim n,r,s:r=Int(100*Rnd+1)*2:do until r=n*2:n=inputbox(s):If(n*2>r)Then:s="-":else:s="+":end if:loop
\$\endgroup\$
0
\$\begingroup\$

Mathematica 66

n=RandomInteger@100;For[,(i=Input[])!=n,Print@If[n>i,"+","-"]];"="
\$\endgroup\$
0
\$\begingroup\$

GWBASIC, 104

1 RANDOMIZE TIMER:Z=INT(RND*100)+1:WHILE Q<>Z:INPUT Q:IF Q<Z THEN ?"+" ELSE IF Q>Z THEN ?"-"
2 WEND:?"="

(just because I can)

\$\endgroup\$
0
\$\begingroup\$

vba, 95

(immediate window)

randomize:z=int(rnd()*100)+1:while q<>z:q=cint(inputbox(q)):?iif(q<z,"+",iif(q>z,"-","=")):wend
\$\endgroup\$
  • \$\begingroup\$ You can use Int instead of CInt. ;-) \$\endgroup\$ – Gaffi Apr 15 '13 at 21:45

Not the answer you're looking for? Browse other questions tagged or ask your own question.