Scrivi una funzione di pluralizzazione per il russo


25

In inglese, i nomi possono assumere due forme diverse a seconda che siano singolari (uno) o plurali (qualsiasi altra cosa). Ad esempio, dovremmo dire "1 cane" ma "2 cani", "0 cani", "57 cani" e così via.

In russo, ci sono tre categorie. Invece di "1 cane, 2 cani, 5 cani", in russo sarebbe "1 собака, 2 собаки, 5 собак".

Le categorie sono divise secondo la seguente logica:

  • "Singolare": utilizzato per 1 e qualsiasi numero che termina con 1, ad eccezione dei numeri che terminano con 11.
    • Esempi: 1 собака, 21 собака, 101 собака
  • "Pochi": usato per 2, 3 e 4 e qualsiasi numero che termina con 2, 3 o 4, tranne per i numeri che terminano con 12, 13 e 14.
    • Esempi: 2 собаки, 3 собаки, 4 собаки, 32 собаки, 43 собаки, 104 собаки
  • "Molti": tutto ciò che non è considerato "Singolare" o "Pochi".
    • Esempi: 0 собак, 5 собак, 11 собак, 13 собак, 25 собак, 111 собак, 114 собак

La sfida

Dato un input intero nell'intervallo [0, 1000], restituisce 1se appartiene alla categoria "singolare", 2se appartiene alla categoria "pochi" e 5se appartiene alla categoria "molti".

Il tuo programma può essere una funzione o può utilizzare STDIN. È possibile stampare su STDOUT o restituire un valore dalla funzione

Questa è una sfida del codice golf , quindi vince la soluzione con il minor numero di byte.



2
Perché 1, 2e 5in particolare? Inoltre, perché non posso usare i codici di uscita?
CalculatorFeline

6
@Phoenix Mi sembra completamente sbagliato - russo rotto - Ho sempre usato il modulo nella domanda e lo trovo corretto, e apparentemente lo è
dkudriavtsev

2
@CalculatorFeline Se inizi a contare da 1, diventi singolare a 1, pochi si verificano per primi a 2, molti prima si presentano a 5.
Ha

5
Contare in russo è estremamente difficile. Vale forse la pena notare che l'ultima cifra determina il caso . 1 = Singolare nominativo 2,3,4 = Singolare genitivo, 5-0 plurale genitivo. Questo cambia con il caso della frase, e poiché ci sono 6 casi, ci sono 24 forme di "uno" (che è maschile), 24 forme di "due" (che è femminile) e così via. Si dice che il professore di russo nella mia università locale non sarebbe in grado di tradurre " con 2345 cani", perché "con" richiede il caso strumentale (difficile).
smirkingman

Risposte:


15

Python 2 , 36 byte

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

Provalo online!

Stessa lunghezza aritmetica:

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

Diamo prima un'occhiata a un codice più semplice che non tiene conto degli adolescenti.

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

Qui, vogliamo una mappatura della propria cifra su un output che funzioni come

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

Ma, piuttosto che prendere il nmodulo 10 ( %10), possiamo fare n%-10, che si associa agli intervalli [-9..0]per fornire i resti:

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

Questo è promettente perché le prime due voci 0e -9sono distanti, e devono essere inviati alle uscite diverse. Inoltre, -10può essere abbreviato in ~9.

Da qui, la divisione del pavimento da /-3dà pezzi di 3 con il punto di partenza giusto

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

Per ottenere l'output desiderato, ora abbiamo solo bisogno di mappare 0->5, 1->5, 2->2, 1->1, cosa che facciamo con la selezione della stringa '5521'[_].

Ora, abbiamo anche bisogno di numeri che finiscono in 11-15 per dare sempre 5. Per prima cosa lo facciamo rilevando se quindi la cifra delle decine è 1. Prendendo n/10per rimuovere l'ultima cifra, quindi applichiamo %~9come prima per ottenere i risultati

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

per le rispettive cifre finali. La cifra di 1 che vogliamo rilevare è mappata al valore estremo -9. La divisione del pavimento -9lo trasforma in 1 e tutto il resto in 0.

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

Infine, facciamo in modo che questo indicatore 1fornisca sempre l'uscita 5. Questo viene fatto spostando bit il risultato di n%~9/-3right dall'indicatore. Il risultato di 0,1,2,3bit-shift si sposta sempre a 0 o 1, il che dà un output di 5 come desiderato.


7
Spiega per favore.
CalculatorFeline


8

Perl 5 , 26 byte

25 byte di codice + -pflag.

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

Provalo online!

Per un altro byte, c'è $_=/(?<!1)[1-4]$/?2-/1$/:5.

Spiegazioni: (sulla versione da 27 byte; il 26 è abbastanza simmetrico)
Sia "singolare" che "pochi" terminano con "non un 1 seguito da una cifra da 1 a 4" (testato con (?<!1)[1-4]$/). In questi casi, il risultato è 2, meno 1 se il numero termina con 1 ( 2-/1$/). Altrimenti, il risultato è 5.


5
tfw Perl batte 05AB1E di un discreto importo.
Erik the Outgolfer

7

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

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

Provalo

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>


1[1-4]può essere 1.e /1$/.test(s)potrebbe essere +s%10==1. Non dimenticare mai unario +!
CalculatorFeline

Grazie, @CalculatorFeline - ben individuato sul primo :)
Shaggy

Non penso che tu abbia bisogno dell'unario +, s%10dovrebbe convertirlo sin un numero.
ETHproductions

Sì, me ne sono reso conto anche, @ETHproductions.
Shaggy,

1
n%10-> n%5salva un byte
Johan Karlsson il

4

Gelatina ,  19  18 byte

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

Un collegamento monadico che prende e restituisce numeri interi non negativi.

Provalo online! oppure vedere i tre gruppi compresi tra 0 e 1000 inclusi in questa suite di test .

Come?

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

1
Spiegazione per favore.
CalculatorFeline

@CalculatorFeline sta ancora lavorando sul golf ...
Jonathan Allan,

@CalculatorFeline bene non riesco a trovare di meglio; spiegazione aggiunta.
Jonathan Allan,

In quale carattere che codifica quei 18 caratteri possono essere rappresentati da 18 byte?
exebook

@exebook Jelly utilizza una propria
tabella

3

05AB1E , 38 19 byte

Usa la presa dell'indice dalla risposta del pitone di Rod

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

Provalo online!

Spiegazione

•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

8
Stai perdendo per Perl, penso che qualcosa non vada qui.
Pavel,

@Phoenix: Sì. O questa sfida è adatta a regex o sto facendo qualcosa di terribilmente sbagliato :) Ad essere onesti, Perl è spesso piuttosto matto.
Emigna,

4
@Enigma ... e i golfisti Perl sono spesso molto bravi, giusto? ;-)
Dada,

@Dada: molto vero!
Emigna,

Spiegazione per favore.
CalculatorFeline


2

Assemblaggio MCxxxx , 123 byte

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:

TiO non supporta questo linguaggio, che viene utilizzato nel gioco Zachtronics Shenzhen I / O , quindi non esiste alcun collegamento per testarlo.

Spiegazione:

Questa è una funzione che accetta l'input tramite la porta XBus x0 e l'output attraverso la porta x1. È troppo lungo per essere eseguito su un MC4000, ma si adatta perfettamente alla memoria di un MC6000. Le porte XBus, per chi non ha familiarità, consentono la trasmissione di pacchetti discreti di dati digitali.

Un'informazione che può essere utile nella lettura di questo: nell'assemblaggio MCxxxx, le istruzioni di test impostano un flag che indica quale ramo dovrebbe essere preso. Le righe che iniziano con +vengono eseguite solo se il test più recente è tornato vero e le righe che iniziano con -sono eseguite solo se il test è stato falso.

Linea per linea:

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

Una nota sul punteggio: l'assemblaggio MCxxxx non ha funzioni di per sé, ma è il più vicino possibile a una funzione: è un programma che si adatta a un singolo nodo di esecuzione, accetta input attraverso una porta e output attraverso un'altra. Di conseguenza, ho segnato questo come una funzione (cioè senza contare i byte necessari per creare un file emulatore MCxxxx valido).



1

Haskell , 62 58 byte

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

Provalo online!

Spiegazione

Questo crea la seguente stringa:

5122255555555555555551222555555122255555512225555551222555555122255555512225555551222555555122255555 ...

Che è una tabella in cui la cella ncontiene la risposta per il nthnumero. La tabella è corretta solo per i primi 100 elementi, quindi il mod.


Puoi spiegare cosa sta succedendo qui? Potresti sicuramente accorciarlo usandof n|s<-"5122255555"=(s++('5'<$[0..9])++cycle s)!!mod n 100
flawr

Non sapevo che fosse possibile!
bartavelle,

1
Ci sono molti altri suggerimenti e trucchi in codegolf.stackexchange.com/questions/19255/… davvero vale la pena leggere =)
flawr

0

Scala, 110 byte

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

0

Turtlèd, 35 byte

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

Provalo online!

Questa funzione richiede che l'input inizi con un>, che immagino sia ok perché python2 usa input semi regolarmente e che necessita di virgolette.

Spiegazione:

!             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

Non >servono uno scopo nella Turtled o è un carattere arbitrario che hai aggiunto all'ingresso?
Shaggy
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.