Преобразовать строку цифр из слов в целое число


19

Преобразуйте строку, содержащую цифры как слова, в целое число, игнорируя начальные нули.

Примеры

  • "four two"-> 42.
  • "zero zero zero one"-> 1.

Предположения

Представленные материалы могут предполагать, что:

  1. Входная строка состоит из разделенных пробелами цифровых слов.
  2. Все слова действительны (в диапазоне «ноль» .. «девять») и строчные. Поведение для пустого ввода не определено.
  3. Входная строка всегда представляет число без знака в пределах диапазона intи никогда не является пустой строкой.

счет

Ответы будут оцениваться в байтах, причем меньшее количество байтов будет лучше.


3
Добро пожаловать на сайт. Есть несколько вещей, которые мы обычно ожидаем от вопросов, которые здесь отсутствуют. Наиболее важным будет объективный критерий оценки, который должны быть у всех задач.
Пшеничный волшебник

3
Кроме того, этот вопрос очень редок по спецификации. Вы должны точно указать, что требуется от представлений без двусмысленности. Одно предложение и пример просто не соответствуют нашим стандартам ясности для вызовов.
Пшеничный волшебник

3
В дополнение к тому, что уже было сказано, у нас есть песочница, где пользователи могут публиковать свои задачи перед тем, как отправлять их на главную. Таким образом, вы будете пропускать меньше информации при создании сообщений. Если вы посмотрите на другие недавние сообщения на сайте с достаточно позитивным восприятием, я думаю, вы увидите, что и ваш вопрос, и решение не совсем соответствуют тому, что мы делаем здесь.
FryAmTheEggman

3
Риск быть педантичным, я хотел бы указать, что range "zero".."nine"не полностью определено.
Несвязанная строка

4
Досадно, что встроенный модуль Interpreter@"SemanticNumber"делает именно это в Mathematica, за исключением того, что он терпит неудачу в строках, начинающихся с zero zero .
Грег Мартин

Ответы:


22

PHP , 74 байта

foreach(explode(' ',$argn)as$w)$n.='793251_8640'[crc32($w)%20%11];echo+$n;

Попробуйте онлайн!

Попытка получить решение, которое не копирует существующие ответы. Я получаю полином от контрольной суммы циклической избыточности 32-битной длины ( crc32 ) для каждого слова, а затем делаю мод 20 и мод 11, чтобы получить смешанные уникальные значения от 0 до 10 (пропущенные 6) для каждой цифры. Затем, используя это уникальное значение, я нахожу фактическую цифру.

| Word  | CRC32      | %20 | %11 | Equivalent digit |
|-------|------------|-----|-----|------------------|
| zero  | 2883514770 | 10  | 10  | 0                |
| one   | 2053932785 | 5   | 5   | 1                |
| two   | 298486374  | 14  | 3   | 2                |
| three | 1187371253 | 13  | 2   | 3                |
| four  | 2428593789 | 9   | 9   | 4                |
| five  | 1018350795 | 15  | 4   | 5                |
| six   | 1125590779 | 19  | 8   | 6                |
| seven | 2522131820 | 0   | 0   | 7                |
| eight | 1711947398 | 18  | 7   | 8                |
| nine  | 2065529981 | 1   | 1   | 9                |

Еще одна 74-байтовая альтернатива CRC32 %493%10: попробуйте онлайн!

Еще одна 74-байтовая альтернатива CRC32 %2326%11: попробуйте онлайн!


PHP , 74 байта

foreach(explode(' ',$argn)as$w)$n.=strpos(d07bfe386c,md5($w)[21]);echo+$n;

Попробуйте онлайн!

Другая альтернатива с такой же длиной принимает 22-й символ md5слова (единственный символ, который дает уникальное значение для каждого слова), а затем использует этот символ для сопоставления с цифрой.


Это крутой ответ
Хуан Себастьян Лосано



6

Желе ,  19  17 байт

Ḳµ7ị“*;nÄƲ]³Ṙ»i)Ḍ

Монадическая ссылка, принимающая список символов с целым числом.

Попробуйте онлайн!

В значительной степени порт моего ответа Python 2.


предыдущий

ḲŒ¿€i@€“©¥q£½¤MÆÑ‘Ḍ

Попробуйте онлайн!

Существует вполне возможно более короткий путь, но это путь , который первым пришел на ум.


Удаление нуля из строки enklact, чтобы избежать уменьшения, потому что not found равно нулю в любом случае ... умно!
Несвязанная строка

1
Ах, я вижу, вы сделали тот же метод, хорошо.
Джонатан Аллан

5

Python 3 , 107 , 91 , 77 , 90 байтов

-16 байтов от Sriotchilism О'Зайк

+13 байт для удаления начальных нулей

lambda s:int(''.join(map(lambda w:str('zeontwthfofisiseeini'.index(w[:2])//2),s.split())))

Попробуйте онлайн!



Хороший! Таким образом, я даже могу полностью удалить разделитель :)
movatica

1
С обновлениями задачи это больше не действует, так как оно включает ведущие нули. :(
Мастер Пшеницы


1
@movatica Ваше исправление неверно. lstripМетод удаляет все символы в строке , которая дана как аргумент, так что «восемь два» становится «IGHT два», как «е» получают раздели. Также «ноль ноль ноль» должен выводить «0», а не выдавать ошибку.
NemPlayer

5

Perl 6 , 35 32 байта

{+uniparse 'SP'~S:g/<</,DIGIT /}

Попробуйте онлайн!

объяснение

{                              }  # Anonymous block
                S:g/<</,DIGIT /   # Insert ",DIGIT " at
                                  # left word boundaries
           'SP'~  # Prepend 'SP' for space
  uniparse  # Parse list of Unicode names into string
 +  # Convert to integer


3

05AB1E , 18 16 байт

#ε6è}.•ƒ/ÿßÇf•Åβ

Попробуйте онлайн.

Объяснение:

#                 # Split the (implicit) input-string on spaces
 ε  }             # Map each string to:
  6è              #  Get the character at 0-based index 6 (with automatic wraparound)
     .•ƒ/ÿßÇf    # Push compressed string "rothuvsein"
              Åβ  # Convert the characters from custom base-"rothuvsein" to an integer
                  # (after which the top of the stack is output implicitly as result)

Посмотрите эту подсказку 05AB1E (раздел Как сжимать строки, не являющуюся частью словаря? ), Чтобы понять, почему .•ƒ/ÿßÇf•это так "rothuvsein".



3

05AB1E , 17 16 байт

•D±¾©xWÄ0•I#HèTβ

Попробуйте онлайн!

Идеальная связь с другим ответом 05AB1E , но с совершенно другим подходом.

•D±¾©xWÄ0•               # compressed integer 960027003010580400
          I#             # split the input on spaces
            H            # convert each word from hex (eg "one" => 6526)
             è           # index (with wrap-around) into the digits of the large integer
              Tβ         # convert from base 10 to integer

3

Сетчатка 0.8.2 , 46 45 байт

\w+
¶$&$&$&
%7=T`r\ot\huvs\ein`d`.
\D

^0+\B

Попробуйте онлайн! Ссылка включает в себя тестовые случаи. Объяснение:

\w+
¶$&$&$&

Поместите каждое слово в отдельную строку и продублируйте его.

%7=T`r\ot\huvs\ein`d`.

Транслитеруйте 7-й символ каждой строки, используя строку @ UnrelatedString.

\D

Удалите все оставшиеся нецифровые символы.

^0+\B

Удалить начальные нули (но оставить хотя бы одну цифру).

Предыдущее 46-байтовое более традиционное решение:

T`z\wuxg`E
on
1
th
3
fi
5
se
7
ni
9
\D

^0+\B

Попробуйте онлайн! Ссылка включает в себя тестовые случаи. Объяснение:

T`z\wuxg`E

Слова zero, two, four, sixи eightоднозначно содержат буквы zwuxg. Транслитеруйте их в четные цифры.

on
1
th
3
fi
5
se
7
ni
9

Для нечетных цифр, просто сопоставьте первые две буквы каждого слова в отдельности.

\D

Удалите все оставшиеся нецифровые символы.

^0+\B

Удалить начальные нули (но оставить хотя бы одну цифру).


2

Желе , 20 18 17 байт

Ḳ7ị“*;nÄƲ]³Ṙ»iƲ€Ḍ

Попробуйте онлайн!

-2 байта от запуска "rothuvsein" через строковый компрессор user202729 .

-1 байт от кражи строки enklact Джонатана Аллана без нуля и помещения ее в несколько иначе структурированную программу.

Ḳ                    Split the input on spaces,
              Ʋ€     for each word
             i       find the 1-based index (defaulting to 0)
   “*;nÄƲ]³Ṙ»        in "othuvsein"
 7ị                  of the element at modular index 7,
                Ḍ    and convert from decimal digits to integer.


2

Japt , 13 байт

¸mg6 ì`Ψuv 

Попытайся

Похоже, что все остальные опровергли мою идею - я мог бы избавить себя от необходимости писать сценарий для грубой силы оптимальной строки для сжатия, только чтобы найти это, вплоть до индекса 1,000,000(это было рано, у меня не было моего кофеина пока нет!) "rothuvsein" - единственно возможная нить!

¸mg6 ì`...     :Implicit input of string
¸              :Split on spaces
 m             :Map
  g6           :  Character at index 6 (0-based, with wrapping)
     ì         :Convert from digit array in base
      `...     :  Compressed string "rothuvsein"

Сжатый строка содержит символы в кодовых 206, 168, 117, 118, 160и 136.


1
... ты действительно пробовал до 1000000? Длина длины имен цифр равна 60 см, поэтому нет смысла пытаться выйти за пределы этого (60 эквивалентно 0, 61 к 1 и т. Д.).
Grimmy

1
@ Грими, было рано, кофеина еще не было! Вставить миллион в сценарий, который я написал, чтобы сгенерировать все возможности, было так же легко, как и любое другое число, и это спасло меня от математических операций на LCM.
Лохматый

2

Рубин , 63 байта , 52 байта , 50 байтов

p $*.map{|d|'rothuvsein'.index (d*3)[6]}.join.to_i

-2 благодаря ценному наконечнику чернил


Добро пожаловать в Code Golf! В Ruby $*это псевдоним ARGV, так что не стесняйтесь использовать его, чтобы сэкономить дополнительные байты.
Value Ink

2

T-SQL, 110 байт

SELECT 0+STRING_AGG(CHARINDEX(LEFT(value,2),'_ontwthfofisiseeini')/2,'')
FROM STRING_SPLIT((SELECT*FROM i),' ')

Разрыв строки предназначен только для удобства чтения.

Ввод осуществляется через таблицу я, В соответствии с нашими правилами ввода - вывода . Я мог бы сохранить 14 байтов, предварительно заполнив строковую переменную, но это допустимо, только если у языка нет других методов ввода.

Объяснение:

  1. STRING_SPLIT берет входную строку и разделяет ее в пробелах
  2. CHARINDEXберет первые 2 символа и возвращает (основанную на 1) позицию в строке '_ontwthfofisiseeini'.'ze'для нуля нет в строке и возвращает 0 для "не найден". Подчеркивание гарантирует, что мы получим кратные только два.
  3. Разделите на 2, чтобы получить окончательную цифру
  4. STRING_AGG разбивает цифры обратно без разделителя
  5. 0+вызывает неявное преобразование в INT и удаляет все начальные нули. 1*также будет работать.

2

машинный код x86, 46 байт

HexDump:

57 53 33 c0 33 ff f6 01 0f 75 15 6a 0a 5b 99 f7
f3 6b ff 0a 03 fa 33 c0 38 01 75 0f 97 5b 5f c3
69 c0 26 2b aa 6e 32 01 c1 e8 02 41 eb d8

Это fastcallфункция - получает указатель на строку в ecxи возвращает результат в eax.

Функция хеширования умножается на магическое число 1856645926, выполняет XORввод входного байта и сдвигает вправо на 2 бита.

Сохранение и восстановление регистров noclobber ( ediи ebx) заняло 4 байта, но я не нашел более эффективного способа реализовать это. Хранение постоянной 10 в ebxбыло особенно раздражающим!

Разборка с соответствующими байтами кода:

57                   push        edi  ; edi = result
53                   push        ebx  ; we use ebx to store the constant 10
33 C0                xor         eax,eax  
33 FF                xor         edi,edi  
    myloop:
F6 01 0F             test        byte ptr [ecx],0Fh  ; check for end of word
75 15                jne         myhash
6A 0A                push        0Ah  
5B                   pop         ebx  
99                   cdq              ; prepare 64-bit dividend in edx:eax
F7 F3                div         eax,ebx  ; find the remainder of division by 10
6B FF 0A             imul        edi,edi,0Ah
03 FA                add         edi,edx  ; update the result
33 C0                xor         eax,eax  ; reset the hash temporary variable
38 01                cmp         byte ptr [ecx],al  ; check for end of input (here al=0)
75 0F                jne         mycontinue
97                   xchg        eax,edi  ; set the return register
5B                   pop         ebx  ; restore registers
5F                   pop         edi  ; restore registers
C3                   ret  
    myhash:
69 C0 26 2B AA 6E    imul        eax,eax,6EAA2B26h  ; hashing...
32 01                xor         al,byte ptr [ecx]  ; hashing...
C1 E8 02             shr         eax,2  ; hashing...
    mycontinue:
41                   inc         ecx  ; next input byte
EB D8                jmp         myloop

Эквивалентный код C:

int doit(const char* s)
{
    int result = 0;
    unsigned temp = 0;
    while (true)
    {
        int c = *s++;
        if ((c & 15) == 0)
        {
            temp %= 10;
            result = result * 10 + temp;
            temp = 0;
            if (c == 0)
                break;
            else
                continue;
        }
        temp *= 1856645926;
        temp ^= c;
        temp >>= 2;
    }
    return result;
}

Как вы нашли магические числа?
Спарклер

Я выполнил поиск по моему C-коду - перепробовал все 32-битные числа и все смены. Есть только несколько возможностей - код найден только один в диапазоне до 2000000000.
Анатолий

Вы можете использовать edx вместо edi (нажмите edx перед idiv, вставьте eax после него, imul с ebx, добавьте eax в edx), чтобы сохранить один байт.
Питер Ферри



1

Древесный уголь , 19 байт

I⍘⭆⪪S §ι⁶rothuvsein

Попробуйте онлайн! Ссылка на подробную версию кода. Порт @ KevinCruijssen's 05AB1E ответа. Объяснение:

    S               Input string
   ⪪                Split on spaces
  ⭆                 Map over words and join
       ι            Current word
      §             Cyclically indexed
        ⁶           Literal `6`
 ⍘       rothuvsein Custom base conversion
I                   Cast to string for implicit print

1

PowerShell , 48 байт

+-join($args|%{'rothuvsein'.indexof(($_*3)[6])})

Попробуйте онлайн!

Использует тот же rothuvseinтрюк, что и другие, благодаря Джонатану Аллану. Ожидает входные аргументы через splatting, который в TIO проявляется как отдельные аргументы командной строки.


1

Котлин, 83 байта

fun String.d()=split(' ').fold(""){a,b->a+"rothuvsein".indexOf((b+b+b)[6])}.toInt()

+1 байт, если вы хотите поддерживать длинные toLong()

Тот же трюк rothuvsein, как и у других, экономя некоторые драгоценные байты благодаря Kotlin's nice toInt()и fold(). Я просто не могу избавиться от ощущения, что можно сбрить еще несколько байтов ...



1

Пакет Windows, 169 байт

@setlocal enabledelayedexpansion
@set z=zeontwthfofisiseeini
:a
@set b=%1
@for /l %%c in (0,2,18)do @if "!b:~0,2!"=="!z:~%%c,2!" set/aa=a*10+%%c/2&shift&goto a
@echo %a%


0

VBA, 160 байт

Function e(s)
s = Split(s, " ")
For i = LBound(s) To UBound(s)
s(i) = Int((InStr("ontwthfofisiseeini", Left(s(i), 2)) + 1) / 2)
Next
e = Val(Join(s, ""))
End Function

Соответствует первым двум символам в строке, исключая ноль.


0

Бакон , 83 72 байта

Предполагая, что строка указана в w $, этот код ищет индекс в «zeontwthfofisiseeini», используя регулярное выражение, основанное на уникальных первых 2 символах каждого слова. Индекс затем делится на 2, обеспечивая правильный результат.

FOR x$ IN w$:r=r*10+REGEX("zeontwthfofisiseeini",LEFT$(x$,2))/2:NEXT:?r
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.