Pedra, Poliglota, Tesoura


68

Escreva um programa poliglota em três idiomas que reproduza pedra-papel-tesoura .

A entrada para qualquer versão do programa é sempre uma das cadeias rockou paperou scissors.

No primeiro idioma, o programa deve produzir a opção pedra-papel-tesoura que supera a entrada:

Input     Output
rock      paper
paper     scissors
scissors  rock

No segundo idioma, o programa deve produzir a opção pedra-papel-tesoura que liga a entrada:

Input     Output
rock      rock
paper     paper
scissors  scissors

No terceiro idioma, o programa deve emitir a opção pedra-papel-tesoura que perde para a entrada:

Input     Output
rock      scissors
paper     rock
scissors  paper

O código mais curto em bytes vence. O desempate é a resposta mais votada.

As entradas e / ou saídas podem opcionalmente ter uma nova linha à direita, mas, caso contrário, devem ser apenas as strings / rock/ simples . Você pode usar letras maiúsculas , , se desejado.paperscissorsROCKPAPERSCISSORS

Você não pode usar versões diferentes da mesma linguagem (por exemplo, Python 2 e 3).


Um erro de idioma pode sair?
precisa saber é o seguinte

2
@KritixiLithos Vá com o meta concenso . "Acho que terminar com um erro ou uma exceção não capturada é bom aqui, desde que não produza saída dispersa para STDOUT."
Calvin Hobbies

2
Nunca com certeza com os poliglotas, os diferentes idiomas podem receber informações de maneiras diferentes?
Jonathan Allan

3
@JonathanAllan Tudo bem. Para alguns conjuntos de idiomas que possuem apenas determinadas formas de entrada, seria necessário.
de

Respostas:


60

Python, brainfuck e JavaScript, 103 99 bytes Yay abaixo de 100 bytes!

0,[.5,];p=["rock","scissors","paper"]
1//1;lambda x:p[p.index(x)-1];"""
x=>p[-~p.indexOf(x)%3]//"""

No Python, isso define uma função que supera a entrada; no cérebro, é apenas um programa simples para gatos; no JavaScript, ele perde. Aqui está uma versão que dá um nome às funções fe também solicita entrada em JavaScript e Python 3:

0,[.5,];p=["rock","scissors","paper"]
1//1;f=lambda x:p[p.index(x)-1];"""
f=x=>p[-~p.indexOf(x)%3]//"""

1//1;"""
console.log(f(prompt())) // JavaScript
1//1"""; print(f(input())) # Python

Experimente online (versão mais antiga): Python , brainfuck , JavaScript

Explicação:

No Python, """..."""é uma string de múltiplas linhas, que pode ser usada como qualquer token. Quando colocado sozinho, não faz nada. Eu uso isso para "ocultar" o código JavaScript do Python. O mesmo vale para o (0,[.5,])bit, é apenas uma tupla contendo uma 0e uma lista de 5, e também a 1//1parte, //em Python é a divisão inteira, mas inicia um comentário em JavaScript. Aqui está o código retirado desses tokens:

p=["rock","scissors","paper"]
lambda x:p[p.index(x)-1]

A primeira linha é bastante auto-explicativa, apenas define a lista ppara conter as diferentes opções em pedra-papel-tesoura. A segunda linha define uma função sem nome que recebe um argumento xe devolve a escolha que é melhor x(por exemplo, o elemento anterior em p)


Em JavaScript, //denota um comentário de linha única. Da mesma forma que no Python, os tokens únicos são ignorados; portanto, o código retirado desses tokens é:

p=["rock","scissors","paper"]
x=>p[-~p.indexOf(x)%3]

Isso funciona de maneira semelhante ao Python, primeiro definindo a lista ppara conter as opções e depois definindo uma função anônima que oferece a opção perdida. -~xé o mesmo x+1mas com maior precedência para que eu possa pular os parênteses.


No brainfuck, todos os personagens exceto +-,.[]<>são removidos, deixando o seguinte:

,[.,][,,]
[.-]
>[-.]

O comando ,lê um byte de entrada, .imprime e faz um [...]loop enquanto o valor é diferente de zero. O que este programa faz então é ler a entrada e imprimi-la um caractere de cada vez até que o caractere \0seja encontrado. Como não temos isso no código, podemos ignorar o restante do programa. Na verdade, isso apenas faz eco ao que o usuário digita, vinculando-o efetivamente.


Estava trabalhando em uma solução muito semelhante, mas você me venceu :). Você precisa atualizar o link Javascript TIO, aliás, é diferente dos outros dois.
DIMP

2
x=>p[p.indexOf(x)+1]||"rock"//"""pode ser encurtado parax=>p[(p.indexOf(x)+1)%3]//"""
Lucas

13
+1 Eu nunca vi Brainfuck tão escondido. Geralmente é óbvio se um poliglota também contém BF. Não neste!
vsz

Eu acho que você pode mover o programa BF em torno de um pouco para salvar um byte ou dois:1//1,[.5,];
ETHproductions

Por uma questão de fato, acho que você pode usar o existente []na segunda linha para salvar mais bytes:1//1,;lambda x:p[p.index(x,0)+-1];"""
ETHproductions

40

Python 2, Ruby, Retina, 90 83 bytes

-7 bytes graças ao Value Ink

s=['rock','paper','scissors']
print s[s.index((0and gets or input()))+(0and-2or-1)]

Experimente on-line: Python , Ruby , Retina

Ganha em Ruby, perde em Python e empata em Retina. Essa solução utiliza o fato de ser verdade 0em Ruby, mas falsa em Python. Também utiliza indexação negativa em Python e Ruby.


andtem precedência de operador or, então s.index(0and STDIN.gets or input())funciona. Além disso, getsé um alias para STDIN.getsRuby.
Valor Ink

10
+1 por não apenas comentar o código de maneiras diferentes!
leo

@ValueInk Thank you! Eu percebi que tinha que haver uma maneira mais concisa para obter a entrada em Ruby, e verifica-se que havia
matemática viciado em

21

V, Brain-flak e Python 2, 97, 86, 81, 77 , 75 bytes

o='rock paper scissors'.split()
lambda s:o[o.index(s)-1]#ddt.C rHd*wywVp

Dois bytes salvos graças a @ nmjcman101!

Isso foi super divertido! Eu gosto muito desta resposta porque é uma visão geral legal dos idiomas que eu gosto: meu editor favorito, meu idioma não esotérico favorito e um idioma que escrevi. (Tecnicamente, o python 3 é melhor, mas o python 2 é mais golfista ¯\_(ツ)_/¯).

Experimente online! em Python (ligeiramente modificado para que você possa ver a saída), que imprime o que perde na entrada.

Experimente online! no Brain-Flak, que imprime o que está relacionado à entrada.

Experimente online! em V, que imprime o que supera a entrada.

Como V depende de caracteres ASCII não imprimíveis, eis um hexdump:

00000000: 6f3d 2772 6f63 6b20 7061 7065 7220 7363  o='rock paper sc
00000010: 6973 736f 7273 272e 7370 6c69 7428 290a  issors'.split().
00000020: 6c61 6d62 6461 2073 3a6f 5b6f 2e69 6e64  lambda s:o[o.ind
00000030: 6578 2873 292d 315d 231b 6464 742e 4320  ex(s)-1]#.ddt.C 
00000040: 720e 1b48 642a 7779 7756 70              r..Hd*wywVp

Explicação:

Pitão

Em python, isso é muito direto. Definimos uma lista dos três elementos e retornamos o elemento imediatamente antes da entrada. Como -1retorna o elemento back, isso funciona circularmente e é tudo muito direto e fácil. Então, tudo depois #é um comentário.

Brain-Flak

Isso também é extremamente direto no cérebro. Se tivéssemos que ganhar ou perder, provavelmente seriam várias centenas de bytes. Mas isso realmente funciona em 0 bytes. No início do programa, toda a entrada é carregada na pilha. No final do programa, toda a pilha é impressa implicitamente.

Depois que removemos todos os caracteres irrelevantes, o código que o cérebro vê é

()[()]

O que simplesmente avalia 1 + -1, mas como esse valor não é usado, é um NOOP.

V

Aqui é onde fica um pouco estranho. Nomear a lista python opode parecer arbitrário, mas definitivamente não é. Em V, oabre uma nova linha e nos coloca no modo de inserção. Então,

='rock paper scissors'.split()
lambda s:o[o.index(s)-1]#

é inserido no buffer. Depois disso, o código relevante é:

<esc>ddxxf'C r<C-n><esc>Hd*wywVp

Explicação:

<esc>                          " Return to normal mode
     dd                        " Delete this line. Now the cursor is on '='
       t.                      " Move the cursor forward to the "'"
         C                     " Delete everything after the "'", and enter insert mode
           r                   " From insert mode, enter '<space>r'
            <C-n>              " Autocomplete the current word based on what is currently in the buffer
                               " Since only one word starts with 'r', this will insert 'rock'
                 <esc>         " Leave back to normal mode
                      H        " Go to the first line (where the input is)
                       d*      " Delete everything up until the next occurence of the input
                         w     " Move forward one word
                          yw   " Yank the word under the cursor
                            Vp " And paste that word over the current line, delete everything else

@WheatWizard Em Python, não há razão também (exceto que é do mesmo tamanho). Mas isso estraga tudo no V.
DJMcMayhem

A @WheatWizard Cause V é uma linguagem muito estranha e é uma tarefa muito estranha para ela. Tudo depende muito do layout dos personagens e .split()é mais fácil se livrar dos vários parênteses e aspas que aparecem na sua solução.
DJMcMayhem

Super menor, mas você pode remover o xxe substituí-lo por a 2para fazer o comando, 2f'pois ='ele será excluído pelo d*posterior de qualquer maneira. EDIT: você pode ser capaz de fazê-lo t.?
precisa saber é o seguinte

@ nmjcman101 Oooh, doce, idéia incrível. Obrigado pela dica!
DJMcMayhem

16

CJam , Retina , PHP, 92 86 85 bytes

ECHO["rock",0,"scissors","paper"][ORD(READLINE())%4];
#];"scissors  paper rock"S/rci=

Deve ser executado em PHP usando a -rflag.

Experimente no CJam

Experimente na Retina

Experimente em PHP

CJam

No CJam, todas as letras maiúsculas são variáveis ​​predefinidas. Na primeira linha, muitos desses valores são enviados para a pilha, junto com alguns literais de string e array. Alguns incrementos, decrementos e outras operações são executadas.

Depois de tudo isso, a pilha é agrupada em uma matriz ( ]) e descartada ( ;), portanto, nada disso importa. O programa principal do CJam é simplesmente:

"scissors  paper rock"S/rci=

"scissors  paper rock"        e# Push this string
                      S/      e# Split it on spaces
                        r     e# Read the input
                         c    e# Cast to char (returns the first character in the string)
                          i   e# Cast to int (its codepoint)
                           =  e# Get the index of the split array (CJam has modular arrays)

Retina

Isso quase parece trapaça ...

Retina substituirá qualquer correspondência da regex ECHO["rock",0,"scissors","paper"][ORD(READLINE())%4];na entrada por #];"scissors paper rock"S/rci=. O que quer que esse regex corresponde, certamente não corresponde a nada em rock, paperou scissors, de forma nenhuma substituição é feita. A entrada não modificada é então emitida implicitamente.

PHP

A segunda linha é um comentário, portanto é ignorada.

A primeira linha usa o mesmo algoritmo que a parte CJam, mas com diferentes ordens dos resultados.


11
As funções TIL PHP não diferenciam maiúsculas de minúsculas.
precisa saber é o seguinte

14

C, C ++, Python; 227 226 216 bytes

Guardou um byte graças a @Mat!

#include<stdio.h>/*
f=lambda a:"rock"if a[0]=="r"else"paper"if a[0]=="p"else"scissors"
"""*/
int f(char*b){puts(sizeof'b'-1?*b=='r'?"paper":*b=='s'?"rock":"scissors":*b=='r'?"scissors":*b=='s'?"paper":"rock");}
//"""

Define uma função fem todos os idiomas. Vitórias em C, empates em Python, perdem em C ++. Como C ++ sempre faz / s

A parte entre the /*e the */é um bloco de comentários em C e C ++, enquanto é a declaração da função lambda em Python. Basicamente, compara o primeiro caractere do argumento da função e retorna a movimentação que começa com essa letra.

A parte entre """s é uma sequência de múltiplas linhas no Python, enquanto é a declaração da função em C e C ++. sizeof'b'-1descobre se o idioma atual é C de C ++. Ele tem um valor verdadeiro se o tamanho for diferente de 1, caso contrário, um valor falso. No caractere C, os literais são do tipo de 4 bytes de comprimento, enquanto no C ++ eles são do tipo de byte único. Depois que o idioma é descoberto, ele apenas olha para a primeira letra da entrada e sai em conformidade.

C

Experimente online!

C ++

Experimente online!

Pitão

Experimente online!


4
"A parte entre o ''" s é um bloco de comentário em Python" É na verdade uma seqüência de várias linhas.
ivzem

10

C ++, R, C; 252 240 226 220 209 bytes

#define b/*
M=function()cat(readline())
#*/
#import<stdio.h>
#define M()main(){int i=0;char t[9];char*u;char*s[]={"rock","paper","scissors"};scanf("%s",t);for(;*t-*s[i++];);puts(s[(i+=sizeof('a')==1)%3]);}
M()

Faz uso da diferença entre C e C ++ que o tamanho de um caractere literal é de 4 bytes em C e 1 byte em C ++.

C ++:

Experimente online!

R:

Resultado:

> #define b/*
> M=function()cat(readline())
> #*/
> #import<stdio.h>
> #define M()main(){int i=0;char t[9];char*u;char*s[]={"rock","paper","scissors"};scanf("%s",t);for(;*t-*s[i++];);puts(s[(i+=sizeof('a')==1)%3]);}
> M()
rock
rock

C:

Experimente online!


8

Gawk, Retina, Perl; 68 bytes

{eval"\$_=uc<>"}{$_=/[Sk]/?"paper":/[Pc]/?"rock":"scissors"}{print}

(com uma nova linha no final)

Gawk (vencedor)

Algum lixo para o Perl, altere o conteúdo da linha ( $_que é o mesmo que $0porque a variável _é indefinida), dependendo de conter um kou a c, e imprima o resultado. Ignore qualquer aviso sobre seqüências de escape, eu pretendia fazer isso.

{a_string_that_is_ignored}
{$_ = /[Sk]/ ? "paper" : /[Pc]/ ? "rock" : "scissors"}
{print}

Retina (laço)

O mesmo truque que o Basic Sunset e outros: substitua correspondências de alguma regexp boba na primeira linha pelo conteúdo da segunda linha, então passe a entrada.

Perl (perdedor)

Leia uma linha e converta-a para maiúscula, escolha uma palavra com base na letra que ela contém e imprima o resultado. A primeira e a última etapa são agrupadas usando evalpara ocultá-las do awk.

$_ = uc <>;
$_ = /[Sk]/ ? "paper" : /[Pc]/ ? "rock" : "scissors";
print $_

Gawk, Retina perl -p; 57 bytes

Estou inserindo isso como um bônus, porque a troca da linha de comando perl -pdeve fazer parte do programa pelas regras usuais deste site, o que tornaria não um poliglota.

{eval"\$_=uc"}$_=/[Sk]/?"paper":/[Pc]/?"rock":"scissors"

Novamente com uma nova linha final para Retina . Desta vez, com perl -pa impressão automática da saída, a sobrecarga de perl é significativamente reduzida. Posso deixar a tarefa $_acionar uma impressão implícita no awk .


Você poderia adicionar um link TIO (ou um compilador on-line semelhante para testar) para cada um deles?
Kevin Cruijssen

@KevinCruijssen Adicionado. A saída no TIO para perl -pestá vazia, deve haver um erro no TIO.
Gilles 'SO- stop be evil'

7

> <>, Retina, Python 2: 144 127 123 bytes

1 byte salvo graças a @Loovjo removendo um espaço

4 bytes salvos graças a @ mbomb007 usando em inputvez deraw_input

#v"PAPER"v?%4-2{"SCISSORS"v?%2:i
#>ooooo; >oooooooo<"ROCK"~<
a="KRS".index(input()[-1])
print["SCISSORS","ROCK","PAPER"][a]

Publicado na TNB como um desafio , decidi experimentar essa combinação de idiomas.

> <>

Experimente online!

O IP começa a se mover para a direita.

#                      Reflect the IP so that it now moves left and it wraps around the grid
i:                     Take one character as input and duplicate it

Os possíveis caracteres que serão inseridos na entrada são PRS(já que o programa usa apenas o primeiro caractere). Seus valores ASCII são 80, 81e 82.

2%                     Take the modulo 2 of the character. Yields 0, 1, 0 for P, R, S respectively
?v                     If this value is non-zero (ie the input was ROCK), go down, otherwise skip this instruction

Se a entrada fosse rock, é isso que aconteceria:

<                      Start moving to the left
~                      Pop the top most value on the stack (which is the original value of R and not the duplicate)
"KCOR"                 Push these characters onto the stack
<                      Move left
oooo                   Output "ROCK" as characters (in turn these characters are popped)
o                      Pop the top value on the stack and output it; but since the stack is empty, the program errors out and exits promptly.

Caso contrário, se a entrada fosse SCISSORSou PAPER, é isso que o IP encontraria:

"SROSSICS"             Push these characters onto the stack
{                      Shift the stack, so the the original value of the first char of the input would come to the top
2-4%                   Subtract 2 and take modulo 4 of the ASCII-value (yields 2, 0 for P, S respectively)
?v                     If it is non-zero, go down, otherwise skip this instruction

Se a entrada foi PAPER, então:

>ooooooooo             Output all characters on the stack (ie "SCISSORS")
<                      Start moving left
o                      Pop a value on the stack and output it; since the stack is empty, this gives an error and the program exits.

Caso contrário (se a entrada foi SCISSORS):

"REPAP"                Push these characters onto the stack
v>ooooo;               Output them and exit the program (without any errors).

Retina

Experimente online!

Nesse caso, a Retina considera cada par de duas linhas como um par de partida e substituição. Por exemplo, ele tenta substituir qualquer coisa que corresponda à primeira linha pela segunda linha, mas, como a primeira linha nunca é correspondida, ela nunca a substitui por nada, preservando a entrada.

Python 2

Experimente online!

O programa Python exige que a entrada seja colocada entre "s.

As duas primeiras linhas são comentários em Python.

a="KRS".index(input()[-1])             # Get the index of the last character of the input in "KRS"
print["SCISSORS","ROCK","PAPER"][a]    # Print the ath index of that array

Eu não acho que o espaço depois printda última linha seja necessário.
Loovjo 12/04

Você pode usar em input()vez de raw_input().
mbomb007

Graças @Loovjo para a ponta :)
Kritixi Lithos

@ mbomb007 Isso não parecem funcionar
Kritixi Lithos

@KritixiLithos ele funciona se a parte python leva entrada com citações
undergroundmonorail

0

Ruby, Clojure, Lisp comum - 251 bytes

(print(eval '(if()({(quote SCISSORS)(quote PAPER)(quote PAPER)(quote ROCK)(quote ROCK)(quote SCISSORS)}(read))(eval(quote(nth(position(read)(quote("SCISSORS""PAPER""ROCK")):test(quote string-equal))(quote(ROCK SCISSORS PAPER))))))))
;'['"'+gets+'"']))

Versão mais legível com espaços em branco:

(print(eval '(if() ; distinguish between CLojure and Common Lisp
    ({(quote SCISSORS)(quote PAPER)(quote PAPER)
       (quote ROCK)(quote ROCK)(quote SCISSORS)}(read)) ; use hash-map as a function
    (eval(quote(nth ; find index of the input arg in the list
       (position(read)(quote("SCISSORS""PAPER""ROCK")):test(quote string-equal))  
    (quote(ROCK SCISSORS PAPER))))))))
 ;'['"'+gets+'"'])) ; ruby indexation

Clojure sempre vence, Ruby sempre empata, Common Lisp sempre perde.

Para Ruby, tudo dentro de 's é uma string. Ele se estende por duas linhas. Em seguida, ele usa o []operador com um argumento string que retorna a própria string, se ela estiver presente na string. O resultado é impresso, Ruby apenas espelha a entrada.

A segunda linha é um comentário para Clojure e Common Lisp. Um monte de evale quotedeve ser usado porque o Clojure precisa garantir que todos os símbolos sejam válidos. Seria bom reutilizar mais o código, mas até a nthfunção tem assinaturas diferentes nesses idiomas. Basicamente, o Clojure é if()avaliado como true e vai para o primeiro ramo quando um mapa de hash de possíveis variantes é chamado com o argumento lido de stdin. O Lisp comum vai para o segundo ramo, encontra a posição do argumento de stdin na lista e retorna o item correspondente da lista resultante.

Eu acho que a parte Common Lisp pode ser mais jogada no golfe.

Veja on-line: Ruby , Common Lisp , Clojure


0

Scala, Javascript e Ok, 167 bytes

s=>{var a="paper,scissors,rock".split(",")/*/**/a[-1]="rock"
return a[a.indexOf(s)-1];`*/a((a.indexOf(s)+1)%3)//`//Ook. Ook. Ook! Ook? Ook. Ook! Ook! Ook. Ook? Ook!
}

Experimente em Scala Experimente em Javascript Experimente a versão cerebral do Ook

Scala - vitórias

s=>{                                                      //define an anonymous function
  var a="paper,scissors,rock".split(",")                  //generate the array
  /* /* */ a[-1]="rock"                                   //scala supports nested comments,
  return a[a.indexOf(s)-1];`                              //so this comment...
  */                                                      //...ends here
  a((a.indexOf(s)+1)%3)                                   //return the winning string
  //`//Ook. Ook. Ook! Ook? Ook. Ook! Ook! Ook. Ook? Ook!  //another comment
}

Javascript - perde

s=>{                                                   //define an anonymous function
  var a="paper,scissors,rock".split(",")               //generate the array
  /*/**/                                               //a comment
  a[-1]="rock"                                         //put "rock" at index -1
  return a[a.indexOf(s)-1];                            //return the string that loses
  `*/a((a.indexOf(s)+1)%3)//`                          //a string
  //Ook. Ook. Ook! Ook? Ook. Ook! Ook! Ook. Ook? Ook!  //a comment
}

Ook! - laços

A parte Ook é o simples programa de gatos ,[.,]fodidos pelo cérebro, transformado em Ook.

s=>{var a="paper,scissors,rock".split(",")/*/**/a[-1]="rock"   //random stuff
return a[a.indexOf(s)-1];`*/a((a.indexOf(s)+1)%3)//`//         //more random stuff
Ook. Ook. Ook! Ook? Ook. Ook! Ook! Ook. Ook? Ook!              //the program
}                                                              //random stuff

Se você usar a[(a.indexOf(s)+2)%3], não precisará definir a[-1]="rock". Além disso, você não pode colocar o código Ook dentro da string JavaScript também?
Neil
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.