Kim bir Rock, Paper, Scissors, Lizard, Spock oyunu kazanır?


24

Orada bu oyun ile ilgili çeşitli sorular , hatta bir yarışması burada . Ancak tüm bu zorlukların ve yarışmaların bir oyunun kazananı otomatik olarak belirlemek için bir yola ihtiyacı olduğunu düşünüyorum. Yani:

Meydan okuma

["rock", "paper", "scissors", "lizard", "spock"]Oyuncu 1 ve oyuncu 2 için seçimleri temsil eden aralıktaki iki giriş göz önüne alındığında , maçın galibi belirlenir.

kurallar

[Winner] [action]    [loser]
-----------------------------
scissors cut         paper
paper    covers      rock
rock     crushes     lizard
lizard   poisons     spock
spock    smashes     scissors
scissors decapitates lizard
lizard   eats        paper
paper    disproves   spock
spock    vaporizes   rock
rock     crushes     scissors

Kısıtlamalar

  • Girdi, verilen aralıktaki bir dize çifti olacaktır (başka hiçbir dize kullanılamaz). İsterseniz karakter dizilerini, belirtilen değerlerden herhangi birini temsil ettiği sürece kullanabilirsiniz.
  • Giriş dizeleri için küçük harf, büyük harf ( "ROCK") veya deve büyük harf ( ) kullanıp kullanmamayı seçebilirsiniz "Rock"; seçilen vaka tüm girişler için aynıdır.
  • Çıktı, kazananı belirleyen ve cevaplar tutarlı olduğu sürece istediğiniz her şey olabilir, değerlerin üçlüsü olacaktır. Örnek: 1ilk giriş kazanırsa, 2ikinci giriş kazanırsa, 0bir kravat varsa. Veya belki Ade ilk giriş kazanırsa, Bikinci giriş kazanırsa, <empty string>bir kravat varsa.

Hedef

Bu , yani her dil için en kısa program / yöntem / fonksiyon / lambda kazanabilir!

Testler

[Input 1] [Input 2] [Output: 1/2/0]
-----------------------------------
 rock      paper     2
 rock      scissors  1
 lizard    spock     1
 spock     rock      1
 spock     paper     2
 rock      rock      0

Bu kum havuzundan geliyor .
Charlie


Bağlantılı sorunun bir kopyası olarak kapattım çünkü 2 yeni değerle aynı soru ve IO'da hafif bir varyasyon var.
Buğday Sihirbazı

4
@WheatWizard bazen girdideki küçük bir değişiklik çok farklı çıktılar üretir. Sorular oldukça benzer olabilir, ancak iki yeni değer dikkate alınması gereken daha fazla vaka yaratır, bu yüzden burada kullanılan algoritmalar insanların tekrar düşünmesini sağlayacak kadar farklıdır ( cakehile ile verilen cevaplara bakınız ).
Charlie

4
Katılıyorum ve yeniden açılmak için oy kullandım.
GB

Yanıtlar:


25

Python 3 , 68 50 48 bayt

EDIT: Neil'den 3, Bay Xcoder'dan 2 numara sayesinde

Her girdi dizgisinin dördüncü bir karakteri vardır, bu yüzden onları ayırt etmek için kullanıyorum. Döngüdeki öğeleri düzenlerseniz (makas, kâğıt, taş, kertenkele, takoz), her bir öğe öğeyi doğrudan bundan sonra vurur ve öğe 3, döngüsel olarak sağa bakar. Böylece girdilerin döngüdeki pozisyonlarını çıkarırız. Bu sayı 0 ise, bu bir bağdır. 1 veya 3 ise, ilk oyuncu için bir galibiyettir. Orijinal çözümümde, çevrim farkı, oyunun sonuçlarını ayırt etmek için "210100" dizisine endekslenir. Neil bir şekilde 7 ekleyerek ve modülü 3 alarak indekslemeden gerçekleştirilebileceğini anladı. Düzenleme: Orijinal olarak dize tanımlamak için ikinci karakteri kullandım, ancak dördüncü kullanıyorsanız ve çevrimi tersine çevirirseniz, kek elde edersiniz. Ve hepimiz daha çok kek kullanabiliriz.

lambda x,y,z="cake".find:(7+z(y[3])-z(x[3]))%5%3

Çevrimiçi deneyin!

Eski versiyon:

lambda x,y,z="caoip".index:(7+z(y[1])-z(x[1]))%5%3

Çevrimiçi deneyin!

Orijinal versiyon:

b="caoip"
def r(x,y):return"210100"[(b.index(y[1])-b.index(x[1]))%5]

Çevrimiçi deneyin!



6
PPCG'ye Hoşgeldiniz!
Steadybox

1
49 bayt: Çevrimiçi deneyin! (anahtarlama .indexiçin .find)
Sayın Xcoder

1
48 bayt: Çevrimiçi deneyin! (Buna ihtiyacınız yok p, "chaoi"yeter)
Bay Xcoder

14

JavaScript (ES6), 56 bayt

Körleme sözdiziminde girdi alır (a)(b). İade 0A kazanır eğer, 1B kazanır eğer, ya falsebir kravat.

a=>b=>a!=b&&a>b^614>>((g=s=>parseInt(s,31)%9)(a)^g(b))&1

gösteri

Nasıl?

H () karma fonksiyonunu şöyle tanımlarız :

H = s => parseInt(s, 31) % 9

Bu verir:

s          | H(s)
-----------+-----
"rock"     |  2
"paper"    |  8
"scissors" |  1
"lizard"   |  3
"spock"    |  4

A ve b iki girişi göz önüne alındığında , aşağıdaki ifadeleri dikkate alıyoruz:

  1. Elimizdeki yok a> b ? (sözlükbilim sırasına göre)
  2. yok b oyunu kazanmak?
  3. değeri ne N = H (a) bir XOR H, (b) ?

(1) ve (2), biz sonucu olmadığını anlamak a> b doğru kazanan almak için ters edilmeli ve biz de bu bayrağı depolamak N-inci bir arama bit maskesi bit.

a        | H(a) | b        | H(b) | N  | a > b | b wins | invert
---------+------+----------+------+----+-------+--------+-------
rock     |   2  | paper    |   8  | 10 | Yes   | Yes    | No
rock     |   2  | scissors |   1  |  3 | No    | No     | No
rock     |   2  | lizard   |   3  |  1 | Yes   | No     | Yes
rock     |   2  | spock    |   4  |  6 | No    | Yes    | Yes
paper    |   8  | rock     |   2  | 10 | No    | No     | No
paper    |   8  | scissors |   1  |  9 | No    | Yes    | Yes
paper    |   8  | lizard   |   3  | 11 | Yes   | Yes    | No
paper    |   8  | spock    |   4  | 12 | No    | No     | No
scissors |   1  | rock     |   2  |  3 | Yes   | Yes    | No
scissors |   1  | paper    |   8  |  9 | Yes   | No     | Yes
scissors |   1  | lizard   |   3  |  2 | Yes   | No     | Yes
scissors |   1  | spock    |   4  |  5 | No    | Yes    | Yes
lizard   |   3  | rock     |   2  |  1 | No    | Yes    | Yes
lizard   |   3  | paper    |   8  | 11 | No    | No     | No
lizard   |   3  | scissors |   1  |  2 | No    | Yes    | Yes
lizard   |   3  | spock    |   4  |  7 | No    | No     | No
spock    |   4  | rock     |   2  |  6 | Yes   | No     | Yes
spock    |   4  | paper    |   8  | 12 | Yes   | Yes    | No
spock    |   4  | scissors |   1  |  5 | Yes   | No     | Yes
spock    |   4  | lizard   |   3  |  7 | Yes   | Yes    | No

Dolayısıyla bitler:

bit | value
----+-----------
 0  | 0 (unused)
 1  | 1
 2  | 1
 3  | 0
 4  | 0 (unused)
 5  | 1
 6  | 1
 7  | 0
 8  | 0 (unused)
 9  | 1
10  | 0
11  | 0
12  | 0

Bunu aşağıdan yukarıya doğru okumak ve baştaki sıfırları yoksaymak, bu sayede 1001100110 veya 614 değerini verir .



4

JavaScript (ES6), 63 54 53 49 bayt

f=
(l,r,g=s=>"cake".search(s[3]))=>(7+g(r)-g(l))%5%3
<div onchange=o.textContent=`RLT`[f(a.selectedOptions[0].value,b.selectedOptions[0].value)]>L: <select id=a><option>Rock<option>Paper<option>Scissors<option>Lizard<option>Spock</select> R: <select id=b><option>Rock<option>Paper<option>Scissors<option>Lizard<option>Spock</select> Winner: <span id=o>T

Golfün limanı @ WhatToDo'nun cevabı. Not: snippet, sayısal sonucu, daha az okunamayan bir şeye dönüştürür. Düzenleme: @Arnauld sayesinde 1 bayt kaydedildi. @Ovs sayesinde 4 byte kurtarıldı.


@ovs Ugh, golfümü WhatToDo'nun cevabını yeterince zor ...
Neil

3

Ruby , 36 bayt

->a,b{(2+a.sum%88%6-b.sum%88%6)%5%3}

İade 01 oyuncu kazanır eğer,1 2 oyuncu kazanır eğer ve 2beraberlik için.

Kullanıcının 507295 cevabı dayanarak, ancak karma gerçekleştirmek için matematiksel bir formül kullanır. modun a.sumtüm ASCII kodlarının toplamıdır a, mod 1<<16ve ilkel bir sağlama toplamı olarak tasarlanmıştır. Karma aşağıdaki kodu kullanarak bulundu:

1.upto(99){|j|p j,["scissors","paper","rock","lizard","spock"].map{|i|i.sum%j%6}}

Bu iki değer üretti j, küçük harflere uygun bir karma verdi, yani her ikisi de azalan diziyi verdi.[3,2,1,0,4] (veya [4,3,2,1,0]spock başlangıcına çevrilirse).

Diğer cevaplarda açıklandığı gibi, yukarıdaki sekanstaki ardışık elemanlar için sabit bir modulo 5 veren bir karma (h[a]-h[b])%5formülün çalışması için gereklidir . Her bir eleman, 1 veya 3 elemanını sağa atıyor ve 2 veya 4 elemanını sağa kaybediyor.

Çevrimiçi deneyin!


3

C, 53 bayt

a="FÈ..J..ÁE";
z=*++y==*++x?0:a[*y&47>>1]>>*++x&7&1+1;

Bu sorunu, iki, beş durum girişi tarafından tanımlanan 25 durum olan bir durum makinesi olarak ele aldım.

Bir dizi dizideki durumların sonuçlarını tanımlayarak. Sonuçları girdiler içinde benzersiz işaretler kullanarak araştırıyorum.

Diğer çözümlerde belirtildiği gibi, karakter 2, 3 ve 4 olası girişler arasında benzersizdir. Cevap dizilimimde uygun biti seçmek için kullandığım 2 ve 3 karakterlerinde yoğunlaştığım.

Karakter 2 içinde, 1'den 4'e kadar olan bitler girişi açıkça tanımlar. Bu bitlerin maskelenmesi ve uygun şekilde kaydırılmasıyla [işte "* y & 47 >> 1"], giriş 0, 1, 4, 7 veya 8 olarak not edilebilir. Bu nedenle cevap dizgimin 9 karakteri vardır. (ilginç bitler ayrılmış)

character 2:
a 61   011 0000 1
c 63   011 0001 1
i 69   011 0100 1
p 70   011 1000 0
o 6f   011 0111 1

Karakter 3 içinde, bitler 0, 1 ve 2 açıkça girişi tanımlar. Bu bitlerin maskelenmesiyle (kaydırma gerekli değildir) [bu "* x & 7"], giriş 0, 1, 2, 3 veya 7 olarak not edilebilir. (ilginç bitler ayrılmış)

character 3
p 70   01110 000
i 69   01101 001
z 7a   01111 010
o 6f   01101 111
c 63   01100 011

Cevap dizesi daha sonra uygun karakterler için bitlerin doldurulmasıyla kolayca hesaplanabilir.

0th char represents X=paper
1st char represents X=scissors
4th char represents X=Lizard
7th char represents X=Rock
8th char represents X=Spock

0th bit represents Y=Paper
1st bit represents Y=Scissors
2nd bit represents Y=Lizard
3rd bit represents Y=Rock
7th bit represents Y=Spock

Yani, Y'nin kazanacağı yerin karakterini ayarlayın.

char  7654 3210   in hex    in ascii
0     0100 0110    46         F
1     1100 1000    c8         È
2     0100 0000    d/c        .
3     0100 0000    d/c        .
4     0100 1010    4a         J
5     0100 0000    d/c        .
6     0100 0000    d/c        .
7     1100 0001    c1         Á
8     0100 0101    45         E

O zaman mantık basit: eğer ikinci karakter aynı ise o zaman çizin, aksi takdirde, y'nin ikinci karakterine göre ascii karakter elde edin ve bitleri x'in üçüncü karakterine kaydırın ve bir tane ekleyin. Bu, beraberlik için 0, x kazanmak için 1 ve y kazanmak için 2 yanıtını verir.


PPCG'ye Hoşgeldiniz! Bu harika, iyi düşünülmüş bir cevap.
FantaC

1

Clojure, 130 118 bayt

-12 bayt tuhaf kullanımımdan kurtularak comp.

(fn[& m](let[[p q](map #(apply +(map int(take 2 %)))m)d(- p q)](cond(= d 0)0(#{5 -16 12 -14 13 1 4 -18 2 11}d)1 1 2)))

Zeki olduğumu sanıyordum, ancak bu diğer bazı cevaplara kıyasla daha naif ve daha uzun sürdü.

Her hareket dizesinin ilk 2 harfini alır, karakter kodlarını alır ve bunları toplar. Daha sonra almak için toplamları çıkarır d. Eğerd 0 ise, kendi beraberlik (0), bu kümesinde ise #{5 -16 12 -14 13 1 4 -18 2 11}p1 kazanır, (1), başka, p2 kazanç (2).

(defn decide [& moves] ; Using varargs so I don't need to duplicate the steps.
  ; Pop the first 2 chars of each string, convert them to their ASCII code, and sum them.
  (let [[p1 p2] (map #(apply + (map int (take 2 %))) moves)
        d (- p1 p2)]

    (cond
      (= d 0) ; A tie
      0

      (#{5 -16 12 -14 13
         1 4 -18 2 11} d) ; P1 Wins
      1

      :else ; P2 Wins
      2)))

P1 kazanırsa tanımlayan "sihirli sayıları" almak için koştum

(let [ms ["rock", "paper", "scissors", "lizard", "spock"]]
  (for [p1 ms
        p2 ms]

    ; Same as above
    (let [[p q] (map #(apply + (map int (take 2 %))) [p1 p2])
          d (- p q)]

      [p1 p2 d])))

Hangi bir listesini oluşturur dHer olası senaryo için değerler :

(["rock" "rock" 0]
 ["rock" "paper" 16]
 ["rock" "scissors" 11]
 ["rock" "lizard" 12]
 ["rock" "spock" -2]
 ["paper" "rock" -16]
 ["paper" "paper" 0]
 ["paper" "scissors" -5]
 ["paper" "lizard" -4]
 ["paper" "spock" -18]
 ["scissors" "rock" -11]
 ["scissors" "paper" 5]
 ["scissors" "scissors" 0]
 ["scissors" "lizard" 1]
 ["scissors" "spock" -13]
 ["lizard" "rock" -12]
 ["lizard" "paper" 4]
 ["lizard" "scissors" -1]
 ["lizard" "lizard" 0]
 ["lizard" "spock" -14]
 ["spock" "rock" 2]
 ["spock" "paper" 18]
 ["spock" "scissors" 13]
 ["spock" "lizard" 14]
 ["spock" "spock" 0])

Sonra galibiyet tablosunu bu çıktıyla karşılaştırdım. Neyse ki 0 dışında herhangi bir "çarpışma" yoktu.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.