Écrire une fonction de pluralisation pour le russe

25

En anglais, les noms peuvent prendre deux formes différentes selon qu'ils sont singuliers (un) ou pluriels (autre chose). Par exemple, nous dirions "1 chien" mais "2 chiens", "0 chien", "57 chiens" et ainsi de suite.

En russe, il existe trois catégories. Au lieu de "1 chien, 2 chiens, 5 chiens", ce serait en russe "1 собака, 2 собаки, 5 собак".

Les catégories sont réparties selon la logique suivante:

  • "Singulier": utilisé pour 1 et tout nombre se terminant par 1, sauf pour les nombres se terminant par 11.
    • Exemples: 1 собака, 21 собака, 101 собака
  • "Peu": utilisé pour 2, 3 et 4 et tout nombre se terminant par 2, 3 ou 4, sauf pour les nombres se terminant par 12, 13 et 14.
    • Exemples: 2 pièces, 3 pièces, 4 pièces, 32 pièces, 43 pièces, 104 pièces, 104 pièces
  • "Beaucoup": tout ce qui n'est pas considéré comme "Singulier" ou "Peu".
    • Exemples: 0 pièce, 5 pièces, 11 pièces, 13 pièces, 25 pièces, 111 pièces, 114 pièces, 114 pièces

Le défi

Étant donné une entrée entière dans la plage [0, 1000], retournez 1si elle appartient à la catégorie "singulier", 2si elle appartient à la catégorie "quelques" et 5si elle appartient à la catégorie "plusieurs".

Votre programme peut être une fonction ou il peut utiliser STDIN. Vous pouvez imprimer sur STDOUT ou renvoyer une valeur à partir de la fonction

Il s'agit d'un défi de golf de code , donc la solution avec le moins d'octets gagne.

Peter Olson
la source
2
@Phoenix Pas en russe.
Peter Olson
2
Pourquoi 1, 2et 5en particulier? Aussi, pourquoi ne puis-je pas utiliser de codes de sortie?
CalculatorFeline
6
@Phoenix Cela me semble complètement faux - russe cassé - j'ai toujours utilisé le formulaire dans la question et je le trouve correct, et apparemment c'est le cas
dkudriavtsev
2
@CalculatorFeline Si vous commencez à compter à partir de 1, vous devenez singulier à 1, peu se produit d'abord à 2, beaucoup apparaissent pour la première fois à 5.
Cela est
5
Compter en russe est extrêmement difficile. Il convient peut-être de noter que le dernier chiffre détermine le cas . 1 = Nominatif singulier 2,3,4 = Génitif singulier, 5-0 Génitif pluriel. Cela change avec le cas de la phrase, et comme il y a 6 cas, il y a 24 formes de «un» (qui est masculin), 24 formes de «deux» (qui est féminin) et ainsi de suite. Il est dit que le professeur de russe de mon université locale ne serait pas en mesure de traduire " avec 2345 chiens", car "avec" exige le cas instrumental (difficile).
smirkingman

Réponses:

15

Python 2 , 36 octets

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

Essayez-le en ligne!

Même longueur arithmétiquement:

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

Examinons d'abord un code plus simple qui ne tient pas compte des adolescents.

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

Ici, nous voulons un mappage du chiffre à une sortie qui fonctionne comme

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

Mais, plutôt que de prendre nmodulo 10 ( %10), nous pouvons le faire n%-10, qui correspond aux intervalles [-9..0]pour donner des restes:

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

Ceci est prometteur parce que les deux premières entrées 0et -9sont éloignés, et ils doivent être envoyés à différentes sorties. En outre, -10peut être raccourci à ~9.

De là, la division du sol par /-3donne des morceaux de 3 avec le bon point de départ

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

Pour obtenir la sortie souhaitée, il nous suffit maintenant de mapper 0->5, 1->5, 2->2, 1->1, ce que nous faisons avec la sélection de chaîne '5521'[_].

Maintenant, nous avons également besoin de chiffres se terminant par 11 à 15 pour toujours donner 5. Nous faisons d'abord cela en détectant si le chiffre des dizaines l'est 1. Prenant n/10pour supprimer le dernier chiffre, nous appliquons ensuite %~9comme précédemment pour obtenir les résultats

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

pour les derniers chiffres respectifs. Le chiffre de 1 que nous voulons détecter est mappé à la valeur extrême -9. La division du sol la -9transforme en 1 et tout le reste en 0.

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

Enfin, nous faisons en sorte que cet indicateur 1donne toujours la sortie 5. Cela se fait en décalant le résultat de n%~9/-3droite par l'indicateur. Le résultat des 0,1,2,3décalages de bits toujours à droite à 0 ou 1, ce qui donne une sortie de 5 comme souhaité.

xnor
la source
7
S'il vous plaît, expliquez.
CalculatorFeline
12

Python 2 , 45 octets

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

Essayez-le en ligne!

Barre
la source
o_O je suis époustouflé ... J'avais 56 octets: \
M. Xcoder
De plus, n'est-ce pas (s+'5'*10+s*9)110 caractères?
CalculatorFeline
@CalculatorFeline hmm, il est temps de prendre un café @. @
Rod
5
@Rod ou un covfefe?
Nick T
8

Perl 5 , 26 octets

25 octets de code + -pindicateur.

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

Essayez-le en ligne!

Pour un octet de plus, il y en a $_=/(?<!1)[1-4]$/?2-/1$/:5.

Explications: (sur la version 27 octets; le 26 est assez symétrique)
"singulier" et "peu" se terminent par "pas un 1 suivi d'un chiffre de 1 à 4" (testé avec (?<!1)[1-4]$/). Dans ces cas, le résultat est 2, moins 1 si le nombre se termine par 1 ( 2-/1$/). Sinon, le résultat si 5.

Dada
la source
5
tfw Perl bat 05AB1E d'une bonne quantité.
Erik the Outgolfer
7

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

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

Essayez-le

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>

Hirsute
la source
1[1-4]peut être 1.et /1$/.test(s)pourrait être +s%10==1. N'oubliez jamais unaire +!
CalculatorFeline
Merci, @CalculatorFeline - bien repéré sur le premier :)
Shaggy
Je ne pense pas que vous ayez besoin d'unaire +du tout, vous s%10devriez convertir sen nombre.
ETHproductions
Ouais, je viens de réaliser cela aussi, @ETHproductions.
Shaggy
1
n%10-> n%5enregistre un octet
Johan Karlsson
4

Gelée ,  19  18 octets

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

Un lien monadique prenant et retournant des entiers non négatifs.

Essayez-le en ligne! ou consultez les trois groupes de 0 à 1000 inclus dans cette suite de tests .

Comment?

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
la source
1
Explication s'il vous plaît.
CalculatorFeline
@CalculatorFeline travaille toujours sur le golf ...
Jonathan Allan
@CalculatorFeline bien je ne peux pas trouver mieux; explication ajoutée.
Jonathan Allan
Dans quel caractère codant ces 18 caractères peuvent être représentés par 18 octets?
exebook
@exebook Jelly utilise sa propre page de codes
GamrCorps
3

05AB1E , 38 19 octets

Utilise l'index-trick de la réponse de Rod en python

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

Essayez-le en ligne!

Explication

•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
la source
8
Vous perdez contre Perl, je pense que quelque chose ne va pas ici.
Pavel
@Phoenix: Ouais. Soit ce défi convient bien aux regex, soit je fais quelque chose de terriblement mal :) Pour être juste, Perl est souvent assez golfique.
Emigna
4
@Enigma ... et les golfeurs Perl sont souvent très bons, non? ;-)
Dada
@Dada: Très vrai!
Emigna
Explication s'il vous plaît.
CalculatorFeline
2

PHP> = 7.1, 44 octets

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

Version en ligne

Jörg Hülsermann
la source
1
3 octets plus court: <?=$argn[-2]!=1&($m=($argn+9)%10)<4?2-!$m:5;.
user63956
2

Assemblage MCxxxx , 123 octets

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

Remarque:

TiO ne prend pas en charge ce langage, qui est utilisé dans le jeu Zachtronics Shenzhen I / O , il n'y a donc pas de lien pour le tester.

Explication:

Il s'agit d'une fonction qui accepte les entrées via le port XBus x0 et les sorties via le port x1. Il est trop long pour s'exécuter sur un MC4000, mais s'intègre bien dans la mémoire d'un MC6000. Les ports XBus, pour ceux qui ne sont pas familiers, permettent la transmission de paquets discrets de données numériques.

Une information qui peut être utile pour lire ceci: dans l'assemblage MCxxxx, les instructions de test définissent un indicateur qui indique quelle branche doit être prise. Les lignes commençant par +ne sont exécutées que si le test le plus récent a renvoyé true, et les lignes commençant par -ne sont exécutées que si le test est faux.

Ligne par ligne:

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

Une note sur la notation: l'assemblage MCxxxx n'a pas de fonctions en soi, mais c'est aussi proche d'une fonction que vous pouvez obtenir - c'est un programme qui tient dans un seul nœud d'exécution, prend l'entrée via un port et sort via un autre. En conséquence, j'ai marqué cela comme une fonction (c'est-à-dire sans compter les octets nécessaires pour créer un fichier d'émulateur MCxxxx valide).

Tutleman
la source
1

Haskell , 62 58 octets

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

Essayez-le en ligne!

Explication

Cela crée la chaîne suivante:

5122255555555555555551222555555122255555512225555551222555555122255555512225555551222555555122255555 ...

C'est un tableau où la cellule ncontient la réponse pour le nthnombre. Le tableau n'est correct que pour les 100 premiers éléments, d'où le mod.

Bartavelle
la source
Pouvez-vous expliquer ce qui se passe ici? Vous pouvez sûrement le raccourcir en utilisantf n|s<-"5122255555"=(s++('5'<$[0..9])++cycle s)!!mod n 100
flawr
Je ne savais pas que c'était possible!
bartavelle
1
Il y a beaucoup plus de trucs et astuces dans codegolf.stackexchange.com/questions/19255/… vaut vraiment la peine d'être lu =)
flawr
0

Scala, 110 octets

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

Turtlèd, 35 octets

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

Essayez-le en ligne!

Cette fonction nécessite que l'entrée commence par un>, ce qui, je suppose, est correct car python2 utilise une entrée semi régulièrement, et cela nécessite des guillemets.

Explication:

!             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
Citron destructible
la source
Est-ce >utile dans Turtled ou s'agit-il d'un caractère arbitraire que vous avez ajouté à l'entrée?
Shaggy