Schreiben Sie eine Pluralisierungsfunktion für Russisch

25

Im Englischen können Substantive zwei verschiedene Formen annehmen, je nachdem, ob sie Singular (eins) oder Plural (alles andere) sind. Zum Beispiel würden wir "1 Hund", aber "2 Hunde", "0 Hunde", "57 Hunde" und so weiter sagen.

Auf Russisch gibt es drei Kategorien. Anstelle von "1 Hund, 2 Hunde, 5 Hunde" wäre es auf Russisch "1 собака, 2 собаки, 5 собак".

Die Kategorien sind nach folgender Logik unterteilt:

  • "Singular": Wird für 1 und für alle Zahlen verwendet, die auf 1 enden, außer für Zahlen, die auf 11 enden.
    • Beispiele: 1 собака, 21 собака, 101 собака
  • "Wenige": Wird für 2, 3 und 4 verwendet und für alle Zahlen, die auf 2, 3 oder 4 enden, mit Ausnahme der Zahlen, die auf 12, 13 und 14 enden.
    • Beispiele: 2 собаки, 3 собаки, 4 собаки, 32 собаки, 43 собаки, 104 собаки
  • "Viele": alles, was nicht als "Singular" oder "Wenige" gilt.
    • Beispiele: 0 собак, 5 собак, 11 собак, 13 собак, 25 собак, 111 собак, 114 собак

Die Herausforderung

Bei einer Ganzzahleingabe im Bereich [0, 1000] wird zurückgegeben, 1ob sie zur Kategorie "Singular" 2gehört , ob sie zur Kategorie "Wenige" gehört und 5ob sie zur Kategorie "Viele" gehört.

Ihr Programm kann eine Funktion sein oder es kann STDIN verwenden. Sie können auf STDOUT drucken oder einen Wert von der Funktion zurückgeben

Dies ist eine Code-Golf- Herausforderung, daher gewinnt die Lösung mit der geringsten Anzahl von Bytes.

Peter Olson
quelle
2
@Phoenix Nicht auf Russisch.
Peter Olson
2
Warum 1, 2und 5im Besonderen? Warum kann ich auch keine Beendigungscodes verwenden?
CalculatorFeline
6
@Phoenix Das klingt für mich so völlig falsch - gebrochenes Russisch - Ich habe immer das Formular in der Frage verwendet und finde es richtig, und anscheinend ist es
dkudriavtsev
2
@CalculatorFeline Wenn Sie mit dem Zählen von 1 beginnen, erhalten Sie Singular bei 1, wenige treten zuerst bei 2 auf, viele erscheinen zuerst bei 5.
Sinnvoll
5
Auf Russisch zu zählen ist extrem schwierig. Es ist vielleicht erwähnenswert, dass die letzte Ziffer den Fall bestimmt . 1 = Nominativ Singular 2,3,4 = Genitiv Singular, 5-0 Genitiv Plural. Dies ändert sich mit dem Fall der Phrase, und da es 6 Fälle gibt, gibt es 24 Formen von "Eins" (was männlich ist), 24 Formen von "Zwei" (was weiblich ist) und so weiter. Es wird gesagt, dass der Professor für Russisch an meiner örtlichen Universität wahrscheinlich nicht in der Lage ist, " mit 2345 Hunden" zu übersetzen , weil "mit" den Instrumentalfall verlangt (ein harter Fall).
Smirkingman

Antworten:

15

Python 2 , 36 Bytes

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

Probieren Sie es online!

Gleiche Länge rechnerisch:

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

Schauen wir uns zunächst einfacheren Code an, der Jugendliche nicht berücksichtigt.

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

Hier wollen wir eine Abbildung der eigenen Ziffer auf eine Ausgabe, die wie folgt funktioniert

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

Aber anstatt nmodulo 10 ( %10) zu nehmen, können wir tun n%-10, was den Intervallen zuordnet [-9..0], um Reste zu geben:

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

Dies ist viel versprechend , da die ersten beiden Einträge 0und -9sind weit voneinander entfernt, und sie müssen verschiedene Ausgänge gesendet werden. Auch -10kann auf gekürzt werden ~9.

Ab hier /-3ergibt die Unterteilung durch 3er-Stücke mit dem richtigen Startpunkt

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

Um die gewünschte Ausgabe zu erhalten, müssen wir nur noch abbilden 0->5, 1->5, 2->2, 1->1, was wir mit der String-Auswahl machen '5521'[_].

Jetzt brauchen wir auch Zahlen, die mit 11 bis 15 enden, um immer zu geben 5. Wir tun dies zuerst, indem wir feststellen, ob dann die Zehnerstelle ist 1. Unter n/10der letzten Ziffer zu entfernen, wenden wir dann nach %~9wie vor um die Ergebnisse zu erhalten

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

für die jeweiligen letzten Ziffern. Die Ziffer 1, die wir ermitteln möchten, wird dem Extremwert zugeordnet -9. Die Unterteilung erfolgt durch -91 und alles andere durch 0.

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

Schließlich geben wir für diesen Indikator 1immer den Wert 5 aus. Dies geschieht durch Bitverschiebung des Ergebnisses von n%~9/-3rechts um den Indikator. Das Ergebnis von 0,1,2,3Bitverschiebungen wird immer nach rechts auf 0 oder 1 verschoben, was je nach Wunsch eine Ausgabe von 5 ergibt.

xnor
quelle
7
Bitte erkläre.
CalculatorFeline
12

Python 2 , 45 Bytes

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

Probieren Sie es online!

Stange
quelle
o_O ich weggeblasen bin ... Ich hatte 56 Byte: \
Herr Xcoder
(s+'5'*10+s*9)Sind das nicht 110 Zeichen?
CalculatorFeline
@CalculatorFeline hmm, Zeit für einen Kaffee @. @
Rod
5
@ Rod oder ein Covfefe?
Nick T
8

Perl 5 , 26 Bytes

25 Byte Code + -pFlag.

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

Probieren Sie es online!

Für ein weiteres Byte gibt es $_=/(?<!1)[1-4]$/?2-/1$/:5.

Erklärungen: (in der 27-Byte-Version; die 26 ist ziemlich symmetrisch)
Sowohl "singular" als auch "few" enden mit "not a 1 gefolgt von einer Ziffer von 1 bis 4" (getestet mit (?<!1)[1-4]$/). In diesem Fall ist das Ergebnis 2, minus 1, wenn die Zahl mit 1 ( 2-/1$/) endet . Ansonsten ist das Ergebnis, wenn 5.

Dada
quelle
5
tfw Perl schlägt 05AB1E um einiges.
Erik der Outgolfer
7

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

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

Versuch es

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>

Zottelig
quelle
1[1-4]kann sein 1.und /1$/.test(s)könnte sein +s%10==1. Vergiss niemals unary +!
CalculatorFeline
Vielen Dank, @CalculatorFeline - auf dem ersten gut gesehen :)
Shaggy
Ich glaube nicht , dass Sie die einstellige brauchen +überhaupt, s%10sollte umwandeln sin eine Zahl.
ETHproductions
Ja, das habe ich auch gemerkt, @ETHproductions.
Shaggy
1
n%10-> n%5speichert ein Byte
Johan Karlsson
4

Jelly ,  19  18 Bytes

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

Ein monadischer Link, der nicht negative ganze Zahlen aufnimmt und zurückgibt.

Probieren Sie es online! oder sehen Sie sich die drei Gruppen von 0 bis 1000 in dieser Testsuite an .

Wie?

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
quelle
1
Erklärung bitte.
CalculatorFeline
@ CalculatorFeline arbeitet immer noch am Golfen ...
Jonathan Allan
@CalculatorFeline gut ich kann nicht besser finden; Erklärung hinzugefügt.
Jonathan Allan
In welcher Zeichenkodierung können diese 18 Zeichen durch 18 Bytes dargestellt werden?
Exebook
@exebook Jelly verwendet eine eigene Codepage
GamrCorps
3

05AB1E , 38 19 Bytes

Verwendet den Index-Trick aus Rods Python-Antwort

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

Probieren Sie es online!

Erläuterung

•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
quelle
8
Sie verlieren gegen Perl, ich glaube, hier stimmt etwas nicht.
Pavel
@Phoenix: Ja. Entweder ist diese Herausforderung gut für Regex geeignet oder ich mache etwas furchtbares falsch :) Um fair zu sein, ist Perl oft ziemlich golfen.
Emigna
4
@Enigma ... und Perl-Golfer sind oft sehr gut, oder? ;-)
Dada
@Dada: Sehr wahr!
Emigna
Erklärung bitte.
CalculatorFeline
2

PHP> = 7.1, 44 Bytes

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

Online Version

Jörg Hülsermann
quelle
1
3 Bytes kürzer: <?=$argn[-2]!=1&($m=($argn+9)%10)<4?2-!$m:5;.
user63956
2

MCxxxx Assembly , 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

Hinweis:

TiO unterstützt diese Sprache, die im Zachtronics-Spiel Shenzhen I / O verwendet wird , nicht. Es gibt also keinen Link, um dies zu testen.

Erläuterung:

Dies ist eine Funktion, die Eingaben über den XBus-Port x0 und Ausgaben über den Port x1 empfängt. Es ist zu lang, um auf einem MC4000 ausgeführt zu werden, passt aber gut in den Speicher eines MC6000. XBus-Ports ermöglichen die Übertragung diskreter digitaler Datenpakete.

Eine Information, die beim Lesen hilfreich sein kann: In der MCxxxx-Assembly setzen die Testanweisungen ein Flag, das angibt, welcher Zweig genommen werden soll. Zeilen, die mit beginnen+ werden nur ausgeführt, wenn der letzte Test true zurückgegeben hat, und Zeilen, die mit beginnen, -werden nur ausgeführt, wenn der Test false war.

Zeile für Zeile:

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

Anmerkung zum Scoring: Die MCxxxx-Assembly verfügt nicht über Funktionen an sich, aber dies kommt einer Funktion so nahe wie möglich - es ist ein Programm, das in einen einzelnen Ausführungsknoten passt, Eingaben über einen Port entgegennimmt und Ausgaben über einen anderen ausgibt. Infolgedessen habe ich dies wie eine Funktion bewertet (dh ohne die für die Erstellung einer gültigen MCxxxx-Emulatordatei erforderlichen Bytes zu zählen).

Tutleman
quelle
1

Haskell , 62-58 Bytes

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

Probieren Sie es online!

Erläuterung

Dadurch wird die folgende Zeichenfolge erstellt:

51222555555555555551222555555122255551222555512225555122255551222555512225555122255551222555 ...

Dies ist eine Tabelle, in der die Zelle ndie Antwort für die nthNummer enthält. Die Tabelle ist nur für die ersten 100 Elemente korrekt, daher die mod.

Bartavelle
quelle
Kannst du erklären, was hier los ist? Sie könnten es sicherlich mitf n|s<-"5122255555"=(s++('5'<$[0..9])++cycle s)!!mod n 100
flawr
Ich wusste nicht, dass das möglich ist!
Bartavelle
1
Es gibt viel mehr Tipps und Tricks in codegolf.stackexchange.com/questions/19255/… wirklich lesenswert =)
Fehler
0

Scala, 110 Bytes

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

Turtlèd, 35 Bytes

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

Probieren Sie es online!

Diese Funktion setzt voraus, dass die Eingabe mit einem> beginnt, was meiner Meinung nach in Ordnung ist, da python2 die Eingabe regelmäßig verwendet und Anführungszeichen benötigt.

Erläuterung:

!             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
Zerstörbare Zitrone
quelle
Erfüllt >Turtled einen Zweck oder ist es ein beliebiges Zeichen, das Sie der Eingabe hinzugefügt haben?
Shaggy