Написати функцію плюралізації для російської мови


25

В англійській мові іменники можуть приймати дві різні форми залежно від того, є вони однини (одна) чи множини (що-небудь ще). Наприклад, ми б сказали «1 собака», але «2 собаки», «0 собак», «57 собак» тощо.

У російській мові існує три категорії. Замість "1 собака, 2 собаки, 5 собак", російською мовою було б "1 собака, 2 собаки, 5 собак".

Категорії поділяються за такою логікою:

  • "Однина": використовується для 1 і будь-якого числа, що закінчується на 1, за винятком чисел, що закінчуються на 11.
    • Приклади: 1 собака, 21 собака, 101 собака
  • "Мало": використовується для 2, 3 і 4 і будь-яке число, що закінчується на 2, 3 або 4, за винятком чисел, що закінчуються на 12, 13 і 14.
    • Приклади: 2 собаки, 3 собаки, 4 собаки, 32 собаки, 43 собаки, 104 собаки
  • "Багато": все, що не вважається "сингулярним" або "мало".
    • Приклади: 0 собак, 5 собак, 11 собак, 13 собак, 25 собак, 111 собак, 114 собак

Змагання

З огляду на ціле число в діапазоні [0, 1000], поверніть, 1якщо воно належить до категорії "однини", 2якщо воно належить до категорії "кілька", і5 якщо він належить до категорії "багато".

Ваша програма може бути функцією або вона може використовувати STDIN. Ви можете надрукувати в STDOUT або повернути значення функції

Це кодове завдання для гольфу , тому рішення з найменшою кількістю байтів виграє.



2
Чому 1, 2і 5зокрема? Крім того, чому я не можу використовувати вихідні коди?
CalculatorFeline

6
@Phoenix Це звучить так абсолютно неправильно для мене - зламана російська мова - я завжди використовував форму у запитанні, і вважаю її правильною, і, мабуть, це є
dkudriavtsev

2
@CalculatorFeline Якщо ви почнете рахувати з 1, ви отримуєте однину в 1, декілька вперше виникає в 2, багато хто вперше з'являється в 5. Має прекрасний сенс :-)
LLlAMnYP

5
Порахувати російською мовою надзвичайно важко. Можливо, варто відзначити, що кінцева цифра визначає випадок . 1 = називний відмінок однини 2,3,4 = однина однини, однина 5-0 Це змінюється у випадку словосполучення, і оскільки існує 6 випадків, існує 24 форми 'один' (який є чоловічим), 24 форми 'два' (що жіноче) і так далі. Кажуть, що професора російської мови в моєму місцевому університеті навряд чи вдасться перекласти " з 2345 собаками", тому що "з" вимагає інструментальної справи (важкий).
усміхнений

Відповіді:


15

Python 2 , 36 байт

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

Спробуйте в Інтернеті!

Арифметично однакова довжина:

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

Давайте спочатку розглянемо простіший код, який не враховує підлітків.

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

Тут ми хочемо відобразити свою цифру до результату, який працює як би

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

Але, замість того, щоб взяти nмодуль 10 ( %10), ми можемо зробити n%-10, який відображає інтервали, [-9..0]щоб дати залишки:

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

Це багатообіцяюче, оскільки перші два записи 0і -9далеко один від одного, і їх потрібно надсилати на різні результати. Також -10можна скоротити до ~9.

Звідси поділ підлоги /-3дає шматки 3 з правильним початковим місцем

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

Щоб отримати бажаний вихід, нам зараз просто потрібно зробити карту 0->5, 1->5, 2->2, 1->1, що ми робимо з вибором рядка '5521'[_].

Тепер нам також потрібні цифри, які закінчуються на 11 - 15, щоб завжди давати 5. Спочатку робимо це, виявляючи, чи є тоді десятки цифр 1. Беручи n/10для видалення останньої цифри, ми застосовуємо, %~9як і раніше, для отримання результатів

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

для відповідних підсумкових цифр. Цифра 1, яку ми хочемо виявити, відображається на екстремальне значення -9. Розбиття підлоги поворотом -9до 1, а все інше до 0.

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

Нарешті, ми робимо, що цей показник 1завжди видає вихід 5. Це робиться шляхом переміщення біта на результат n%~9/-3право на індикатор. Результат 0,1,2,3завжди біт зміщується вправо до 0 або 1, що дає вихід 5 за бажанням.


7
Будь ласка, поясніть.
КалькуляторFeline


8

Perl 5 , 26 байт

25 байт коду + -pпрапор.

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

Спробуйте в Інтернеті!

Ще один байт є $_=/(?<!1)[1-4]$/?2-/1$/:5.

Пояснення: (у версії на 27 байт; у 26 досить симетрично)
і "однини", і "кілька" закінчуються на "не 1", а потім цифра від 1 до 4 "(перевірена (?<!1)[1-4]$/). У цьому випадку результат дорівнює 2, мінус 1, якщо число закінчується на 1 ( 2-/1$/). В іншому випадку результат, якщо 5.


5
tfw Perl б'є 05AB1E на неабияку суму.
Ерік Аутгольфер

7

JavaScript (ES6), 53 49 48 40 39 38 37 36 байт

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

Спробуй це

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]може бути 1.і /1$/.test(s)могло бути +s%10==1. Ніколи не забувай одинаку +!
CalculatorFeline

Дякую, @CalculatorFeline - добре помічений на першому :)
Shaggy

Я не думаю, що вам взагалі потрібен одинар +, s%10слід перетворити sна число.
ETHproductions

Так, тільки що зрозумів, що це @ETHproductions.
Кудлатий

1
n%10-> n%5рятує байт
Йохан Карлссон

4

Желе ,  19  18 байт

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

Монадічне посилання, що приймає та повертає невід’ємні цілі числа.

Спробуйте в Інтернеті! або переглянути три групи від 0 до 1000 включно в цьому тестовому наборі .

Як?

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
Пояснення будь ласка.
CalculatorFeline

@CalculatorFeline все ще працює над гольфом ...
Джонатан Аллан

@CalculatorFeline добре, я не можу знайти краще; пояснення додано.
Джонатан Аллан

У якому кодуванні цих 18 символів може бути представлено 18 байт?
exebook

@exebook Jelly використовує власну кодову сторінку
GamrCorps

3

05AB1E , 38 19 байт

Використовує індекс-трюк з відповіді питона Рода

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

Спробуйте в Інтернеті!

Пояснення

•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
Ти програєш Перлу, я думаю, що тут щось не так.
Павло

@Phoenix: Так. Або цей виклик добре підходить для виродження, або я роблю щось страшно неправильне :) Якщо бути справедливим, Perl часто є досить гофрованим.
Емінья

4
@Enigma ... і гольфісти Perl часто дуже хороші, правда? ;-)
Дада

@Dada: Дуже правда!
Емінья

Пояснення будь ласка.
CalculatorFeline


2

MCxxxx Асамблея , 123 байт

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

Примітка:

TiO не підтримує цю мову, яка використовується в грі Zachtronics Shenzhen I / O , тому немає посилання для перевірки цього.

Пояснення:

Це функція, яка приймає вхід через порт XBus x0, а виводить через порт x1. Це занадто довго для виконання на MC4000, але добре вписується в пам'ять MC6000. Порти XBus, для незнайомих, дозволяють передавати дискретні пакети цифрових даних.

Один фрагмент інформації, який може бути корисним для читання цього: у збірці MCxxxx тестові інструкції встановлюють прапор, який вказує, яку гілку слід взяти. Рядки, які починаються з, +виконуються лише у тому випадку, якщо останній тест повернув істину, а рядки, які починаються з цього, -виконуються лише у випадку, якщо тест був помилковим.

Рядок за рядком:

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

Примітка про підрахунок балів: складання MCxxxx не має функцій, але це наближено до функції, яку ви можете отримати - це програма, яка вписується в один вузол виконання, приймає введення через один порт і виводить через інший. У результаті я оцінив це як функцію (тобто без підрахунку байтів, необхідних для створення дійсного файла емулятора MCxxxx).



1

Хаскелл , 62 роки 58 байт

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

Спробуйте в Інтернеті!

Пояснення

Це будує наступний рядок:

5122255555555555555551222555555122255555512225555551222555555122255555512225555551222555555122255555 ...

Яка таблиця, у комірці якої nє відповідь на nthчисло. Таблиця правильна лише для перших 100 елементів, отже, і для mod.


Чи можете ви пояснити, що тут відбувається? Ви, безумовно, можете скоротити його, використовуючиf n|s<-"5122255555"=(s++('5'<$[0..9])++cycle s)!!mod n 100
недолік

Я не знав, що це можливо!
bartavelle

1
Існує набагато більше порад і підказок у codegolf.stackexchange.com/questions/19255/… дійсно варто прочитати =)
flawr

0

Scala, 110 байт

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

0

Turtlèd, 35 байт

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

Спробуйте в Інтернеті!

Ця функція вимагає, щоб вхід починався з>, що, напевно, нормально, оскільки python2 використовує вхідний файл регулярно, і для цього потрібні лапки.

Пояснення:

!             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

Чи >служить цілі в Turtled або це довільний символ, який ви додали до вхідних даних?
Кудлатий
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.