Schere-Stein-Papier in nicht-Python

Alles, was nicht direkt mit Python-Problemen zu tun hat. Dies ist auch der perfekte Platz für Jobangebote.
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Moin,

ich beginne mal mit nem Zitat (http://www.python-forum.de/viewtopic.ph ... 14#p200914):
Hyperion hat geschrieben:So, ich denke der Thread hat das Potenzial für Lösungen in verschiedenen Sprachen!
da es in letzter Zeit mehr als einen Thread über Schere-Stein-Papier gab und es ja auch offtopic ist, starte ich hier in nem seperaten Thread im Offtopic-Bereich. Den Anfang mache ich mit Befunge:

Code: Alles auswählen

00  v                                                                        
>   v >" :srossic)s( ro ,repa)p( ,kco)r( esoohC" v                           
,   4 +>        v                    >\1+\"'kcor' dias retupmoc :esol uoy"  v
,   :  |-*3+67:,<"invalid input '"< >|                                      ,
:   7  ,      >             v   >$^  > 1+ "'repap' dias retupmoc :niw uoy",>v
*   *  ,               > v  >  #\  >^              >  v                      
2   *  7      ^-g07g06_^ #      |-*+3*455:<        ^_v                      ,
5   v  6  v     \<    ^-p07**7:4< >:4:7**-| v:<     - #       v          <  ,
  v0?3^+         |-3:\<                   >4# ^ >v  ->,,.25*,v>,:345**2--|  ,
    2  3         \                |-+2**7:4:\p0< ,  2  >v>v>v""          , ",
  > > ^>*,        v > |  #    >v            #  6 :  *  """",, c          , y,
^<        <      >    >25*:,,           " :eroc"#6 v*  s'es,,:o          . o,
>:3-                ^>+\       #      v     7  # 5 "5  c :o,,em          5 u,
^ ,,,,,,,,,,,,,,,<   1       >1+     v      *  : 2 s4  id l,,rp          2  ,
 >,,,,,,,,,,,,,,,^   \   #   |`   <         *  \ *  3  sic ,,ou           * w,
^,#               <  |-g06g05<              7  p * r:  saou,,ct          , i,
^,#    ,,,,,,"A draw"<   <     >       v    0  0 2 e,  osmo,,se>v        @ n,
 ,                       ^               <  p  5 - y^ <r py,, r,,           :,
 ^"you win: computer said 'scissors'"<      -  : - a">vsru",,"",,            ,
    v"you lose: computer said 'paper'"<    v_v ~^_vlp+\'et,,,>^,,          c,
    >,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,v    ^ 6#< ^,,<""1v""",,,  ,,          o,
^                                   <   <  0       >^\>^>^>^>,,^>v         m,
       v"you win: computer said 'rock'"<   g      >  |         v <         ",
       >,,,,,,,,,,,,,,,,,,,,,,,,,,,,,>  ^  >70g2+-^  >1+"'kcor' dias retup"^,
^                                                              < ,,,,,,,,,,,<
Zum Beweis, dass es funktioniert:

Code: Alles auswählen

$ befunge rps.bef
Choose (r)ock, (p)aper, or (s)cissors: p
you win: computer said 'rock'

Choose (r)ock, (p)aper, or (s)cissors: s
you lose: computer said 'rock'

Choose (r)ock, (p)aper, or (s)cissors: t
invalid input 't'

Choose (r)ock, (p)aper, or (s)cissors: r
you lose: computer said 'paper'

Choose (r)ock, (p)aper, or (s)cissors: s
you win: computer said 'paper'

Choose (r)ock, (p)aper, or (s)cissors: s
A draw

Choose (r)ock, (p)aper, or (s)cissors: p
you win: computer said 'rock'

player score: 3 
computer score: 2
Edit: kleinen Fehler im Code behoben, der beim Kopieren entstanden sein muss (ein Leerzeichen hat gefehlt, ist das denn sonst keinem aufgefallen? :P)
Edit2: 2 Kommata am rechten Rand richtig ausgerichtet. Ich beschuldige mal wieder phpBB dafür
Zuletzt geändert von derdon am Donnerstag 16. Juni 2011, 14:59, insgesamt 2-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wow! Jetzt verrate doch mal, wie Du das geschafft hast? Gibt es da Compiler, die in Befunde übersetzen? Oder ist das wirklich per Hand gemacht? Wenn ja, wie lernt man das? :K
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

@Hyperion
Ach das ist doch noch machbar, Brainfuck ist schlimmer, allerdings einfacher von der Syntax. Man braucht bei den esoterischen Sprachen doch nur ein *wenig* Zeit. :D

Allerdings würde es mich auch interessieren ob das per Hand entstanden ist.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Ja, ist per Hand entstanden. Hab allerdings auch 4 Tage dafür gebraucht, weil mein Hirn einige Pausen benötigte :D Ohne den genialen Debugger, der im Befunge-Interpreter meiner Wahl eingebaut ist, hätte ich wahrscheinlich nach 10 Minuten aufgegeben! Hier ist der Befunge-Interpreter zu finden, den ich nutze: https://github.com/programble/befungee

Edit:
Hyperion hat geschrieben: Wenn ja, wie lernt man das?
Dazu reichte mir die Wikipedia-Seite aus, die ja hauptsächlich eine Referenz der Kommandos darstellt.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

derdon hat geschrieben:Ja, ist per Hand entstanden.
Respekt!
derdon hat geschrieben:
Hyperion hat geschrieben: Wenn ja, wie lernt man das?
Dazu reichte mir die Wikipedia-Seite aus, die ja hauptsächlich eine Referenz der Kommandos darstellt.
Ok; ich hätte jetzt gedacht, dass es da gewisse Pattern / Idiome gibt, die man einmal kapiert haben muss und die man irgend wo lernen kann :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

@derdon
Von mir ebenfalls: Respekt! - auch wenn da noch ein paar Leerzeichen drin sind :)
An der unteren linken Ecke könnte man zumindest noch deutlich etwas ausbessern.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

@Hyperion: Naja, was man vielleicht als Idiom sehen kann, ist wie man Zeichenketten ausgeben kann ohne ganz viele Komma zu tippen: http://de.wikipedia.org/wiki/Befunge#Hello_World. Wie man sieht, habe ich aber trotzdem oft die Länge der Strings benutzt und dementsprechend oft ein Komma getippt. Der Grund ist der, dass mein Stack z.B. mit [0,1] endet, was bedeutet, dass es 0 zu 1 für den Computer steht. Die verlinkte Methode zur Ausgabe von Strings gibt aber *alle* Elemente des Stacks als Zeichen aus. Also brauche ich einen Stopzeichen, bei dem die Schleife aufhört, den Stack zu entleeren. Das habe ich u.a. bei "computer score: " gemacht, wo ich den Doppelpunkt als Stopper genommen habe und dann anschließend noch den Doppelpunkt und das Leerzeichen nachträglich mittels Komma ausgeben musste. Das ist der Teil (leicht verändert, damit er lauffähig ist; das V und die 5 am Fang habe ich hier hinzugefügt, um eine Beispielpunktzahl zu haben):

Code: Alles auswählen

v
5v          <
v>,:345**2--|
""          ,
 c           ,
:o          .
em          5
rp          2
ou          *
ct          ,
se          @
 r,           
""           
>^           
Ausgabe: "computer score: 5"

Edit: für dieses Beispiel unnötige Zeichen entfernt
Zuletzt geändert von derdon am Donnerstag 16. Juni 2011, 15:14, insgesamt 1-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Naja, solche Sachen muss man erst einmal erinnerlichen. Du solltest ein Tutorial schreiben:

"Dive into Befunge", "Learn Befunge the hard way" oder natürlich auch ... "Befunge - the Open Book" *duck* :twisted:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Also ich würde das ganze immer in kleine Funktionen packen, so wie ich das in Brainfuck gemacht habe, zB.

Code: Alles auswählen

52*\0" :ero"v
v"mputer sc"<
>"oc">:v   
     ^,_$.,:
Das könnte man dann einfach so implementieren:

Code: Alles auswählen

53*432v
v     <       <
>52*\0" :ero"v
 v"mputer sc"<
 >"oc">:v   
      ^,_$.,: |   
              @
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Deine erste Version gibt nach der ersten Ausgabe von "computer score: 0" nur noch Nullen aus und terminiert nicht, weil nach dem Doppelpunkt kein @ folgt und der Interpreter (wie bei dem Snake-Spiel) am ende Einer Zeile wieder am Anfang beginnt. Die Ausgabe der zweiten Version ist

Code: Alles auswählen

computer score: 2 
computer score: 3 
computer score: 4 
computer score: 15
und am Ende bleibt noch der Wert 0 im Stack. Aber du hast Recht: in meinem Code gibt es einiges zu verbessern. Dazu müsste ich allerdings am besten von vorne anfangen und viel planen, um mir nix zu verbauen. Hab ich aber keine Lust zu. Außerdem bin ich froh, dass es überhaupt läuft :)

Wo bleiben denn überhaupt die ganzen anderen Versionen?
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

derdon hat geschrieben:Wo bleiben denn überhaupt die ganzen anderen Versionen?
Du hast die Latte einfach zu hoch gehängt ... :?
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

@derdon
Du hast nicht richtig gelesen. Das erste Beispiel ist die *Funktion* das zweite zeigt wie man diese benutzen kann, ist so also vollkommen richtig.
Die 0 am Ende bleibt ja nur drin weil der leere Stack bei ":" eine doppelte Null produziert, das könnte also am Interpreter liegen. Ich bin mir aber nicht sicher was die Spezifikation der Sprache dazu sagt, ansonsten muss man diese vor dem "@" einfach terminieren.

Edit: Eine Schwachstelle hat die Funktion aber noch. "computer score: 0" kann nur einmal am Anfang ausgegeben werden, danach wird die Null als Abbruchsignal interpretiert. Hier sollte man vieleicht irgendeinen hohen Wert definieren und die Abfrage nicht wie im Standardfall bei "|" auf 0, sondern auf den definierten Wert prüfen.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
naeg
User
Beiträge: 33
Registriert: Dienstag 27. April 2010, 11:53

derdon hat geschrieben: Wo bleiben denn überhaupt die ganzen anderen Versionen?
Das lass ich mir nicht zweimal sagen ;)

Hier meine Lösung in Prolog (SWI-Prolog):

Code: Alles auswählen

% 0 = rock
% 1 = paper
% 2 = scissors

get_choices(User, PC) :-
  get_code(User1),
  User is User1 - 48,
  random(A),
  PC is round(A * 10) mod 3.

rps(0) :-
  get_choices(User, PC),
  write('User choice:'),  write(User),
  write('   PC choice:'), write(PC),
  write(' --> '),
  (  User = PC
  -> write('Draw!')
  ;  rps(User, PC)
  ).

rps(2, PC) :-
  (  PC = 0
  -> print('PC won')
  ;  print('You won')
  ).

rps(User, PC) :-
  (  User is PC - 1
  -> print('PC won')
  ;  print('You won')
  ).

Code: Alles auswählen

?- rps(0).
|: 1
User choice:1   PC choice:2 --> PC won
true.

?- rps(0).
|: 2
User choice:2   PC choice:2 --> Draw!
true.

?- rps(0).
|: 0
User choice:0   PC choice:1 --> PC won
true.

?- rps(0).
|: 2
User choice:2   PC choice:1 --> You won
true .

?- rps(0).
|: 1
User choice:1   PC choice:0 --> You won

?- rps(0).
|: 2
User choice:2   PC choice:2 --> Draw!
true.
Sie funktioniert zwar, aber ich bin nicht 100% zufrieden damit (schon lange kein Prolog mehr programmiert).
Zuerst überprüfe ich mit rps(2, PC) ob der User Schere(2) gewählt hat, falls dann noch der PC Stein(0) hat, gewinnt PC. Ansonsten Spieler.
Wenn der Benutzer nicht 2 gewählt hat, gewinnt der PC wenn die Wahl von PC um 1 höher ist als die des Spielers ist. Falls nicht, gewinnt der Spieler.
mfg naeg
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Xynon1 hat geschrieben:@derdon
Du hast nicht richtig gelesen. Das erste Beispiel ist die *Funktion* das zweite zeigt wie man diese benutzen kann, ist so also vollkommen richtig.
Achso, dann war das ein Missverständnis.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Nochmal SWI-Prolog:

Code: Alles auswählen

?- op(300, xfx, beats).

rock beats scissors.
paper beats rock.
scissors beats paper.

play :-
    play(user, computer).

play(Player1, Player2) :-
    findall(Throw, Throw beats _, Throws),
    apply(Player1, [Throws, Throw1]),
    apply(Player2, [Throws, Throw2]),
    evaluate(Player1, Throw1, Player2, Throw2, WinnerInfo),
    apply(show, WinnerInfo).

user(Throws, Throw) :-
    forall(nth1(N, Throws, Throw),
        write_join([Throw, ' (', N, ') '])), 
    write('? '),
    get_char(C), atom_number(C, N),
    nth1(N, Throws, Throw).

computer(Throws, Throw) :-
    N is random(3) + 1,
    nth1(N, Throws, Throw).

evaluate(A, Throw, B, Throw, [Throw, A, B]).
evaluate(A, ThrowA, B, ThrowB, [A, ThrowA, B, ThrowB]) :-
    ThrowA beats ThrowB.
evaluate(A, ThrowA, B, ThrowB, [B, ThrowB, A, ThrowA]) :-
    ThrowB beats ThrowA.

show(Throw, A, B) :-
    writeln('draw:'),
    write_join([A, ' and ', B, ' both threw ', Throw]), nl.
show(Winner, WinnerThrow, Loser, LoserThrow) :-
    write_join([Winner, ' threw ', WinnerThrow, ' and won.']), nl,
    write_join([Loser, ' threw ', LoserThrow, '.']), nl.

write_join([Z]) :-
    !, write(Z).
write_join([X|Y]) :-
    write(X),
    write_join(Y).
EDIT: Hab's nochmal prologischer gemacht.
Zuletzt geändert von pillmuncher am Sonntag 26. Juni 2011, 16:04, insgesamt 2-mal geändert.
In specifications, Murphy's Law supersedes Ohm's.
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Hier in Scheme (allerdings ziemlich hässlicher Code, ich bin grade nich so fit...)

Code: Alles auswählen

(define (contains ls what)
  (find (lambda (x) (equal? x what)) ls))

(define stdin
  (transcoded-port (standard-input-port)
                   (make-transcoder (utf-8-codec))))

(define (get-selection-from-stdin msg choices)
  (display msg)
  (let ([choice (get-line stdin)])
    (cond
      [(contains choices choice)]
      [else
        (printf "Illegal input '~a'\n" choice)
        (get-selection-from-stdin msg choices)])))

(define (random-choice choices)
  (list-ref choices (random (length choices))))

(define (bool b) (if b #t #f))

(define (player-wins? a b)
  (unless (equal? a b)
          (bool (contains '("pr" "sp" "rs") (string-append a b)))))

(let loop [(player-score 0) (computer-score 0)]
  (printf "\n\nScores: You ~a   Computer ~a\n" player-score computer-score)
  (let [(player-choice (get-selection-from-stdin "[r]ock, [p]aper or [s]cissors? " '("r" "p" "s")))
        (computer-choice (random-choice '("r" "p" "s")))]
    (printf "Computer used ~a -- " computer-choice)
    (case (player-wins? player-choice computer-choice)
      [(#t) (display "you win") (loop (add1 player-score) computer-score)]
      [(#f) (display "you loose") (loop player-score (add1 computer-score))]
      [else (display "draw") (loop player-score computer-score)])))

Code: Alles auswählen

Scores: You 0   Computer 0
[r]ock, [p]aper or [s]cissors? p
Computer used s -- you loose

Scores: You 0   Computer 1
[r]ock, [p]aper or [s]cissors? p
Computer used p -- draw

Scores: You 0   Computer 1
[r]ock, [p]aper or [s]cissors? p
Computer used p -- draw

Scores: You 0   Computer 1
[r]ock, [p]aper or [s]cissors? p
Computer used s -- you loose

Scores: You 0   Computer 2
[r]ock, [p]aper or [s]cissors? p
Computer used r -- you win
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Rock-Paper-Scissors-Lizard-Spock in Prolog:

Code: Alles auswählen

?- op(300, xfy, [beats, and]).

rock beats scissors and lizard.
paper beats rock and spock.
scissors beats paper and lizard.
lizard beats spock and paper.
spock beats scissors and rock.

play :-
    play(user, computer).

play(Player1, Player2) :-
    findall(Throw, Throw beats _, Throws),
    apply(Player1, [Throws, Throw1]),
    apply(Player2, [Throws, Throw2]),
    evaluate(Player1, Throw1, Player2, Throw2, WinnerInfo),
    apply(show, WinnerInfo).

user(Throws, Throw) :-
    forall(nth1(N, Throws, Throw),
        write_join([Throw, ' (', N, ') '])), 
    write('? '),
    get_char(C), atom_number(C, N),
    nth1(N, Throws, Throw).

computer(Throws, Throw) :-
    length(Throws, M),
    N is random(M) + 1,
    nth1(N, Throws, Throw).

evaluate(A, Throw, B, Throw, [Throw, A, B]).
evaluate(A, ThrowA, B, ThrowB, [A, ThrowA, B, ThrowB]) :-
    ThrowA beats ThrowB and _ ; ThrowA beats _ and ThrowB.
evaluate(A, ThrowA, B, ThrowB, [B, ThrowB, A, ThrowA]) :-
    ThrowB beats ThrowA and _ ; ThrowB beats _ and ThrowA.

show(Throw, A, B) :-
    writeln('draw:'),
    write_join([A, ' and ', B, ' both threw ', Throw]), nl.
show(Winner, WinnerThrow, Loser, LoserThrow) :-
    write_join([Winner, ' threw ', WinnerThrow, ' and won.']), nl,
    write_join([Loser, ' threw ', LoserThrow, '.']), nl.

write_join([Z]) :-
    !, write(Z).
write_join([X|Y]) :-
    write(X),
    write_join(Y).
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Prolog sieht eigentlich interessant aus. Benutzt das noch irgendwer?
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

mkesper hat geschrieben:Prolog sieht eigentlich interessant aus. Benutzt das noch irgendwer?
Nicht das ich's wirklich nutze, aber ich hatte da mal ein Tutorial für mich (und einen Freund) geschrieben...

Stefan
Benutzeravatar
naeg
User
Beiträge: 33
Registriert: Dienstag 27. April 2010, 11:53

mkesper hat geschrieben:Prolog sieht eigentlich interessant aus. Benutzt das noch irgendwer?
Soweit ich weiß wird Prolog schon noch verwendet, speziell im Bereich Computer Linguistik und KI. Außerdem in speziellen Sachen wie kompliziertere Auswahlmechanismen (z.B. Programm zur Auswahl von potenziellen Kunden für Werbung nach bestimmten Kriterien)

Eines des bekanntesten und sehr gutes Tutorial ist Learn Prolog Now: http://www.learnprolognow.org

Ich würde mich aber nie davon leiten lassen ob und wieviel Verwendung eine Sprache findet. Ich kann dir nur raten Prolog zu lernen wenn es dich interessiert. Der Deklarative Ansatz erlaubt es dir Probleme aus einem komplett neuen Blickwinkel zu sehen. Abgesehen davon ist es einfach an Eleganz nicht zu übertreffen wenn du einen Sudoku-Löser in ca. 15 Zeilen schreiben kannst ;) (mit Constraints).
mfg naeg
Antworten