Escreva uma função de pluralização para russo

25

Em inglês, os substantivos podem assumir duas formas diferentes, dependendo de serem singulares (uma) ou plural (qualquer outra coisa). Por exemplo, diríamos "1 cachorro", mas "2 cães", "0 cães", "57 cães" e assim por diante.

Em russo, existem três categorias. Em vez de "1 cão, 2 cães, 5 cães", em russo, seria "1 pessoa, 2 pessoas, 5 pessoas".

As categorias são divididas de acordo com a seguinte lógica:

  • "Singular": usado para 1 e qualquer número que termina em 1, exceto para números que terminam em 11.
    • Exemplos: 1 собака, 21 собака, 101 itens
  • "Poucos": usados ​​para 2, 3 e 4 e qualquer número que termina em 2, 3 ou 4, exceto para números que terminam em 12, 13 e 14.
    • Exemplos: 2 pçs, 3 pçs, 4 pçs, 32 pçs, 43 pçs, 43 pçs, 104 pçs
  • "Muitos": qualquer coisa que não seja considerada "Singular" ou "Pouca".
    • Exemplos: 0 itens, 5 itens, 11 itens, 13 itens, 25 itens, 111 itens, 114 itens, 114 itens

O desafio

Dada uma entrada inteira no intervalo [0, 1000], retorne 1se pertencer à categoria "singular", 2se pertencer à categoria "poucos" e 5se pertencer à categoria "muitos".

Seu programa pode ser uma função ou pode usar STDIN. Você pode imprimir em STDOUT ou retornar um valor da função

Este é um desafio de código de golfe , portanto, a solução com o menor número de bytes vence.

Peter Olson
fonte
2
@ Phoenix Não está em russo.
Peter Olson
2
Por que 1, 2e 5em particular? Além disso, por que não consigo usar códigos de saída?
CalculatorFeline
6
@Phoenix que soa tão completamente errado para mim - quebrado Russo - Eu sempre usei a forma na questão e acho que é corrigir e, aparentemente, é
dkudriavtsev
2
@CalculatorFeline Se você começa a contar a partir de 1, fica singular em 1, poucas ocorrem primeiro em 2, muitas aparecem em 5. Faz todo sentido :-)
LLlAMnYP
5
Contar em russo é extremamente difícil. Talvez valha a pena notar que o dígito final determina o caso . 1 = Nominativo singular 2,3,4 = Genitivo singular, 5-0 Genitivo plural. Isso muda com o caso da frase e, como existem 6 casos, existem 24 formas de 'um' (masculino), 24 formas de 'dois' (feminino) e assim por diante. Dizem que o professor de russo na minha universidade local dificilmente conseguiria traduzir " com 2345 cães", porque 'com' exige o caso instrumental (um caso difícil).
smirkingman

Respostas:

15

Python 2 , 36 bytes

lambda n:'5521'[n%~9/-3>>n/10%~9/-9]

Experimente online!

Mesmo comprimento aritmeticamente:

lambda n:5/(n%~9/-3>>n/10%~9/-9or 1)

Vamos primeiro olhar para um código mais simples que não leva em consideração os adolescentes.

lambda n:'5521'[n%~9/-3]

Aqui, queremos um mapeamento do dígito da pessoa para uma saída que funcione como

[5, 1, 2, 2, 2, 5, 5, 5, 5, 5][n%10]

Mas, em vez de usar o nmódulo 10 ( %10), podemos fazer n%-10, que mapeia os intervalos [-9..0]para fornecer os restantes:

> [n%~9 for n in range(10)]
[0, -9, -8, -7, -6, -5, -4, -3, -2, -1]

Este é promissor porque as duas primeiras entradas 0e -9estão distantes, e eles precisam ser enviados para diferentes saídas. Além disso, -10pode ser reduzido para ~9.

A partir daqui, a divisão do piso /-3fornece pedaços de 3 com o ponto de partida certo

> [n%~9/-3 for n in range(10)]
[0, 3, 2, 2, 2, 1, 1, 1, 0, 0]

Para obter a saída desejada, agora precisamos apenas mapear 0->5, 1->5, 2->2, 1->1, o que fazemos com a seleção de strings '5521'[_].

Agora, também precisamos de números que terminem em 11 a 15 para sempre dar 5. Primeiro, fazemos isso detectando se o dígito das dezenas é 1. Tomando n/10para remover o último dígito, aplicamos %~9como antes para obter os resultados

[0, -9, -8, -7, -6, -5, -4, -3, -2, -1]

para os respectivos dígitos finais. O dígito 1 que queremos detectar é mapeado para o valor externo -9. A divisão do piso -9transforma em 1 e todo o resto em 0.

> [k%~9/-9 for k in range(10)]
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0]

Finalmente, fazemos com que esse indicador 1sempre dê a saída 5. Isso é feito deslocando o resultado da n%~9/-3direita pelo indicador. O resultado de 0,1,2,3sempre muda de bit para 0 ou 1, o que fornece uma saída de 5, conforme desejado.

xnor
fonte
7
Por favor explique.
CalculadoraFeline
12

Python 2 , 45 bytes

lambda n,s='5122255555':(s+'5'*10+s*8)[n%100]

Experimente online!

Cajado
fonte
o_O Estou deslumbrado ... Eu tinha 56 bytes: \
Sr. Xcoder
Além disso, não são (s+'5'*10+s*9)110 caracteres?
CalculadoraFeline
@CalculatorFeline hmm, o tempo para obter um café @ @.
Rod
5
@Rod ou um covfefe?
Nick T
8

Perl 5 , 26 bytes

25 bytes de código + -psinalizador.

$_=/1.$|[5-90]$/?5:2-/1$/

Experimente online!

Para mais um byte, existe $_=/(?<!1)[1-4]$/?2-/1$/:5.

Explicações: (na versão de 27 bytes; o 26 é bastante simétrico)
Ambos "singular" e "poucos" terminam com "não um 1 seguido por um dígito de 1 a 4" (testado com (?<!1)[1-4]$/). Nesse caso, o resultado é 2, menos 1 se o número terminar com 1 ( 2-/1$/). Caso contrário, o resultado será 5.

dada
fonte
5
O Perl vence 05AB1E por uma quantia justa.
Erik the Outgolfer
7

JavaScript (ES6), 53 49 48 40 39 38 37 36 bytes

n=>/[05-9]$|1.$/.test(n)?5:1+(n%5>1)

Tente

f=
n=>/[05-9]$|1.$/.test(n)?5:1+(n%5>1)
oninput=_=>o.innerText=f(+i.value);o.innerText=f(i.value=0)
<input id=i type=number><pre id=o>

Shaggy
fonte
1[1-4]pode ser 1.e /1$/.test(s)poderia ser +s%10==1. Nunca esqueça unário +!
CalculatorFeline
Obrigado, @CalculatorFeline - bem-visto no primeiro :)
Shaggy
Eu não acho que você precisa do unário +, s%10deve converter spara um número.
ETHproductions
Sim, acabei de perceber isso também, @ETHproductions.
Shaggy
1
n%10-> n%5salva um byte
Johan Karlsson
4

Geléia ,  19  18 bytes

DµṖṚi1’ȧṪị“M;ọ6’D¤

Um link monádico que recebe e retorna números inteiros não negativos.

Experimente online! ou veja os três grupos de 0 a 1000, inclusive nesta suíte de testes .

Quão?

DµṖṚi1’ȧṪị“M;ọ6’D¤ - Main link: non-negative number, n  e.g. 301      311      313
D                  - cast to decimal list                [3,0,1]  [3,1,1]  [1,3,3]
 µ                 - monadic chain separation, call that d
  Ṗ                - pop d                               [3,0]      [3,1]    [1,3]
   Ṛ               - reverse                             [0,3]      [1,3]    [3,1]
     1             - literal 1
    i              - first index of (0 if not found)      0          1        2      
      ’            - decrement                           -1          0        1
        Ṫ          - tail d                               1          1        3
       ȧ           - logical and                          1          0        3
                 ¤ - nilad followed by link(s) as a nilad:
          “M;ọ6’   -   base 250 literal = 1222555555
                D  -   cast to decimal list [1,2,2,2,5,5,5,5,5,5]
         ị         - index into (1-based and modular)     1          5        2
Jonathan Allan
fonte
1
Explicação, por favor.
CalculatorFeline
@CalculatorFeline ainda trabalhando em golfe ...
Jonathan Allan
@CalculatorFeline bem, não consigo encontrar melhor; explicação adicionada.
Jonathan Allan
Em qual caractere que codifica esses 18 caracteres pode ser representado por 18 bytes?
exebook
@exebook Jelly utiliza a sua própria página de código
GamrCorps
3

05AB1E , 38 19 bytes

Usa o truque de índice da resposta python de Rod

•1rꢰ•©5T×®9×JIт%è

Experimente online!

Explicação

•1rꢰ•              # push the number 5122255555
       ©             # store a copy in register
        5T×          # push 5 repeated 10 times
           ®         # retrieve the first number from register
            9×       # repeat it 9 times
              J      # join everything to string
               Iт%   # push input mod 100
                  è  # use this to index into the string of digits
Emigna
fonte
8
Você está perdendo para Perl, acho que algo está errado aqui.
Pavel
@ Phoenix: Sim. Ou esse desafio é bem adequado para regex ou estou fazendo algo terrivelmente errado :) Para ser justo, Perl geralmente é bastante desafiador.
Emigna 31/05
4
@ Enigma ... e os jogadores de Perl costumam ser muito bons, certo? ;-)
Dada
@ Dadá: Muito verdade!
Emigna
Explicação, por favor.
CalculatorFeline
2

PHP> = 7.1, 44 bytes

<?=$argn[-2]!=1&($m=($argn+9)%10)<4?2-!$m:5;

Versão Online

Jörg Hülsermann
fonte
1
3 bytes mais curto: <?=$argn[-2]!=1&($m=($argn+9)%10)<4?2-!$m:5;.
precisa saber é o seguinte
2

Montagem MCxxxx , 123 bytes

e:slx x0
mov x0 acc
dst 2 0
tlt acc 11
-tgt acc 14
-jmp v
+dgt 0
teq acc 1
+mov 1 x1
+jmp e
tlt acc 5
+mov 2 x1
v:-mov 5 x1

Nota:

O TiO não suporta esse idioma, usado no jogo Zachtronics Shenzhen I / O , portanto não há link para testar isso.

Explicação:

Esta é uma função que recebe entrada pela porta XBus x0 e sai pela porta x1. É muito longo para ser executado em um MC4000, mas se encaixa perfeitamente na memória de um MC6000. As portas XBus, para quem não conhece, permitem a transmissão de pacotes discretos de dados digitais.

Uma informação que pode ser útil para ler isso: na montagem MCxxxx, as instruções de teste definem um sinalizador que indica qual ramificação deve ser executada. As linhas que começam com +são executadas apenas se o teste mais recente retornou verdadeiro, e as linhas que começam com -são executadas apenas se o teste for falso.

Linha por linha:

e:slx x0    # Label this line e, then sleep until input is available on XBus port x0
mov x0 acc  # Move the input into register acc 
dst 2 0     # Set the leftmost digit of the input to 0
tlt acc 11  # Test if the value in acc is less than 11
-tgt acc 14 # If it's not, check if it's greater than 14
-jmp v      # If it's not, jump to the line labeled v (the last line)
+dgt 0      # If either of the previous tests returned true,
            #     set acc to the value of acc's rightmost digit
teq acc 1   # Test if acc equals 1
+mov 1 x1   # If it does, return 1
+jmp e      # Then jump to label e, which ends execution
tlt acc 5   # Test if acc is less than 5
+mov 2 x1   # If it is, return 2
v:-mov 5 x1 # If the previous test is false, return 5

Uma observação sobre a pontuação: o assembly MCxxxx não possui funções em si, mas é o mais próximo possível de uma função - é um programa que se encaixa em um único nó de execução, recebe entrada por uma porta e sai por outra. Como resultado, marquei isso como uma função (ou seja, sem contar os bytes necessários para criar um arquivo de emulador MCxxxx válido).

Tutleman
fonte
1

Haskell , 62 58 bytes

f n|s<-"5122255555"=(s++('5'<$[0..9])++cycle s)!!mod n 100

Experimente online!

Explicação

Isso cria a seguinte string:

5122255555555555555551222555555122255555512225555551222555555122255555512225555551222555555122255555 ...

Qual é a tabela em que a célula ncontém a resposta para o nthnúmero. A tabela está correta apenas para os 100 primeiros elementos, daí o mod.

bartavelle
fonte
Você pode explicar o que está acontecendo aqui? Você certamente poderia reduzi-lo utilizandof n|s<-"5122255555"=(s++('5'<$[0..9])++cycle s)!!mod n 100
flawr
Eu não sabia que isso era possível!
bartavelle
1
Há muito mais dicas e truques em codegolf.stackexchange.com/questions/19255/... realmente vale a pena leitura =)
flawr
0

Scala, 110 bytes

n=>Stream.iterate("512225555555555555555")(_=>"1222555555").flatMap(_.toCharArray).map(_.toInt).take(n-1).head
Fénix
fonte
0

Turtlèd, 35 bytes

!--.(1#0#)+.@3(1@1)(2@2)(3@2)(4@2),

Experimente online!

Essa função requer que a entrada comece com um>, o que eu acho que está bem, porque python2 usa entrada semi regularmente e isso precisa de aspas.

Explicação:

!             input the number as a string, complete with the >
 --.          wrap around to the end of the string, and then move one back. if this
              is a single digit, we end up on the >,
              otherwise we end up on the second to last digit. write the digit/>

    (1#0#)    if it is 1, set the string to 0. this way it will always write 3 at the end.



          +.       write the last digit (or 0 if the second last digit was 1)
            @3      set the character variable to 3. this means if what was written was not
                       in (1, 2, 3, 4), then it will write 3 at the end
              (1@1)    if the character written was a 1, set the character to be written
                       at the end to 1
                   (2@2)(3@2)(4@2)
                     if it is any of 2,3,4, set the character to be written at the end to 2
                                  ,    write the character that was set
Limão destrutível
fonte
Será que >servem a um propósito em turtled ou é um caráter arbitrário que você adicionou à entrada?
Shaggy