Гольф мой Ада массивов

10

Фон

Ада - это язык программирования, который не совсем известен своей краткостью.

Тем не менее, его синтаксис литерала массива теоретически может допускать довольно краткие спецификации массивов. Вот простое EBNF-описание литерального синтаксиса массива ( передаваемого в bottlecaps.de :

array ::= positional_array | named_array
positional_array ::= expression ',' expression (',' expression)*
                   | expression (',' expression)* ',' 'others' '=>' expression
named_array ::= component_association (',' component_association)*
component_association ::= discrete_choice_list '=>' expression
discrete_choice_list ::= discrete_choice ('|' discrete_choice)*
discrete_choice ::= expression ('..' expression)? | 'others'

Для простоты мы ограничимся одномерными массивами целых чисел. Это означает, что мы будем использовать только целые числа для значений выражения. Возможно, в будущем мы могли бы попробовать что-то более продвинутое (например, объявление переменных и многомерных массивов). Вы не должны играть в гольф целочисленные литералы .

Вот несколько примеров литералов массива Ada и эквивалентного представления на языке Python для ясности:

(1, 2, 3) = [1, 2, 3]
(1, others => 2) = [1, 2, 2, ..., 2]
(others => 1) = [1, 1, ..., 1]
(1 => 1, 2 => 3) = [1, 3]
(1|2 => 1, 3 => 2) = [1, 1, 2]
(1 => 1, 3 => 2, others => 3) = [1, 3, 2, 3, 3, ..., 3]

Вызов

Цель этой задачи - вывести кратчайший литерал массива Ada с количеством байтов для заданного входного массива. Обратите внимание, что массивы Ada могут начинаться с любого желаемого индекса, поэтому вы можете выбрать желаемый начальный индекс, если каждое значение является последовательным. В этом примере я выбираю начинать с 1, что является идиоматическим для Ады, однако вы можете начать с любого другого целого числа.

вход

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

Вывод

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

Целые числа должны быть представлены в виде десятичных чисел со знаком, как в примерах. Эта задача не охватывает гольф целых значений.

Примеры

Вот некоторые примеры:

Simple: [1, 2, 3] -> (1,2,3)
Range: [1, 1, 1, 1, 1, 1, 1,] -> (1..7=>1)
Others: [1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1] -> (6=>2,others=>1)
Multiple Ranges: [1,1,1,1,1,2,2,2,2,2,1,1,1,1,1,2,2,2,2,2,1,1,1,1,1] -> (6..10|16..20=>2,others=>1)
Tiny Ranges: [1,1,2,2,1,1,1,1,1] -> (3|4=>2,others=>1)
Far Range: [[1]*5, [2]*100, [3]*5] -> (1..5=>1,6..105=>2,others=>3)
Alternation: [1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2] -> (1|3|5|7|9|11|13|15|17=>1,others=>2)
Big Number: [1234567890,1,1234567890] -> (2=>1,1|3=>1234567890)
Big-ish Number: [1234567,1,1234567] -> (1234567,1,1234567)
Solo: [-1] -> (1=>-1)
Huge Input: [[0],[1]*1000000000] -> (0,others=>1)
Positional Others: [1, 2, 3, 3, 3, 3, 3, 3] -> (1,2,others=>3)
Range and Choice, no Others: [1,1,1,12,12,3,3,3,3,3,3,3,3,3,3,4] -> (1..3=>1,4|5=>12,6..15=>3,16=>4)

Минимальные требования

  • Поддержка не менее 100 номеров и входов не менее 256 номеров в длину.

  • Произведите правильный результат для всех таких входов

    • Включает в себя «другие» в конце
    • Включает в себя размещение индекса для отдельных элементов массива
  • Завершите (предпочтительно на TIO) для каждого из указанных выше входов менее чем за минуту.

Самое короткое решение в байтах побеждает!

Реализация эталона

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

Эта реализация использует входные данные в качестве массива, где каждый символ является числом. Заглавные буквы - это специальные константы для больших значений. Аргумент программы - это «начальный индекс» для использования.

Раздел «код» в ссылке TIO является правильным решением проблемы, в то время как «верхний и нижний колонтитулы» реализуют структуру теста.

LambdaBeta
источник
3
Существует ли случай «Дальнего диапазона» просто для того, чтобы указать, что мы можем принимать входные данные в этом формате, если мы выберем, или подчеркнуть, что мы должны иметь возможность обрабатывать этот входной формат, а также обычные массивы? Кроме того, разве последний тест не должен просто выводиться (-1)?
Лохматый
3
Случай «Дальний диапазон» просто написан таким образом, чтобы сэкономить место, фактический ввод будет представлять собой плоский массив, состоящий из 110 целых чисел, но вывод будет правильным. Его цель - продемонстрировать случаи, когда ключевое слово «другие» должно иметь более короткий диапазон и более длинное представление. ( 106..110=>3,others=>2будет длиннее) В последнем случае должен быть индекс, так как грамматика не допускает позиционные массивы из одного элемента ( positional_array ::= expression ',' expression (',' expression)*)
LambdaBeta
1
1(1=>1,others=>1)(1..100000000=>1)
2
Не могли бы вы подтвердить, что (1|3=>1234567,2=>1)это еще один действительный выход для [1234567,1,1234567]?
Арно
1
Разрешено ли использовать Аду в качестве нашего языка?
Бенджамин Уркхарт

Ответы:

5

JavaScript (ES6),  307  304 байта

Сохранено 2 байта благодаря @KevinCruijssen

Это смущающе долго ...

a=>[b=([...a,m=''].map(o=(v,i)=>(i?p==v?!++n:m=o[(o[p]=[o[p]&&o[p]+'|']+(n?i-n+(n>1?'..':'|')+i:i))[m.length]?(x=i-n,j=p):j]:1)&&(p=v,M=n=0)),Object.keys(o).map(k=>j-k|!m[6]?o[k]+'=>'+k:O,O='others=>'+j).sort()),1/a[1]?[...a]:b,j-a.pop()?b:a.slice(0,x-1)+[,O]].map(a=>M=M[(s=`(${a})`).length]||!M?s:M)&&M

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

Arnauld
источник
305 байтов (-2) путем создания переменной для дублируемого 'others=>'.
Кевин Круйссен
@KevinCruijssen Спасибо! (NB: в вашей версии tиспользуется до того, как он будет определен; причина, по которой он не падает, заключается в том, что первые 2 тестовых примера не используют его вообще; тем не менее, это можно легко исправить бесплатно).
Арнаулд
Ах хорошо. Я не разгласил твой ответ, чтобы увидеть, что и где использовалось. Я просто заметил, что у вас было 'others'два раза, и попытался создать переменную для него, не меняя вывод. ;) Спасибо за объяснение этого, и хороший гольф запятой с помощью [,O]. :)
Кевин Круйссен
2

05AB1E , 136 134 132 байта

"',ý'(ì')«ˆ"©.V"θ…ˆ†=>쪮.V"Uγ¨D€gPi˜IX.V}\ÙεQƶ0KDāαγ€g£}D2Fε¾iεнyg≠iyθyg<i'|ë„..}ý}}ë˜}'|ý„=>«Iyнн<è«}Ю.VgFDN._ć'>¡X.V}\¼}¯éIgi¦}н

РЕДАКТИРОВАТЬ: Исправлено для всех тестовых случаев сейчас.

Попробуйте онлайн или проверьте все контрольные примеры (кроме «Огромного ввода», так как он слишком большой).

Объяснение:

"',ý'(ì')«ˆ"       # Push this string (function 1), which does:
 ',ý              '#  Join a list by ","
    '(ì           '#  Prepend a "("
       ')«        '#  Append a ")"
          ˆ        #  Pop and add it to the global array
            ©      # Store this string in the register (without popping)
             .V    # And execute it as 05AB1E code on the (implicit) input-list
"θ…ˆ†=>쪮.V"      # Push this string (function 2), which does:
 θ                 #  Pop and push the last element of the list
  …ˆ†=>ì           #  Prepend dictionary string "others=>"
        ª          #  Append that to the list which is at the top of the stack
         ®.V       #  And execute function 1 from the register     
             U     # Pop and store this string in variable `X`
γ                  # Get the chunks of equal elements in the (implicit) input-list
 ¨                 # Remove the last chunk
  D                # Duplicate the list of remaining chunks
   g              # Get the length of each
     Pi     }      # If all chunk-lengths are 1:
       ˜           #  Flatten the list of remaining chunks
        I          #  Push the input-list
         X.V       #  Execute function 2 from variable `X`
             \     # Discard the top of the stack (in case we didn't enter the if-statement)
Ù                  # Uniquify the (implicit) input-list
 ε                 # Map each unique value `y` to:
  Q                #  Check for each value in the (implicit) input-list if it's equal to `y`
                   #  (1 if truthy; 0 if falsey)
   ƶ               #  Multiply each by its 1-based index
    0K             #  Remove all 0s
      D            #  Duplicate it
       ā           #  Push a list [1, length] without popping the list itself
        α          #  Get the absolute difference at the same indices
         γ         #  Split it into chunks of the same values
          g       #  Get the length of each
            £      #  And split the duplicated indices-list into those parts
                   # (this map basically groups 1-based indices per value.
                   #  i.e. input [1,1,2,1,1,2,2,1,1] becomes [[[1,2],[4,5],[8,9]],[[3],[6,7]]])
 }D                # After the map: duplicate the mapped 3D list
   2F              # Loop 2 times:
     ε             #  Map the 3D list of indices to:
      ¾i           #   If the counter_variable is 1:
        ε          #    Map each list `y` in the 2D inner list to:
         н         #     Leave the first value
         ygi      #     And if there is more than one index:
             yθ    #      Push the last value as well
             yg<i  #      If there are exactly two indices:
              '|  '#       Push string "|"
             ë     #      Else (there are more than two indices)
              „..  #       Push string ".."
                 #      And join the first and last value by this string
        }}         #    Close the if-statement and map
      ë            #   Else:
       ˜           #    Flatten the 2D list
      }'|ý        '#   After the if-else: join by "|"
          „=>«     #   Append "=>"
       yнн         #   Get the very first index of this 2D list
          <        #   Decrease it by 1 to make it 0-based
      I    è       #   And index it into the input-list to get its value again
            «      #   Which is also appended after the "=>"
                 #  After the map: triplicate the result
       ®.V         #  Execute function 1 from the register
       g           #  Get the amount of items in the triplicated list
        F          #  Loop that many times:
         D         #   Duplicate the list
          N._      #   Rotate it the index amount of times
          ć        #   Extract the head; pop and push remainder and head
           '>¡    '#   Split this head by ">"
              X.V  #   And then function 2 is executed again from variable `X`
        }\         #  After the loop: discard the list that is still on the stack
          ¼        #  And increase the counter_variable by 1
                 # After looping twice: push the global array
     é             # Sort it by length
      Igi }        # If the input only contained a single item:
         ¦         #  Remove the very first item
           н       # And then only leave the first item
                   # (which is output implicitly as result)

Посмотрите эту подсказку 05AB1E (раздел Как сжимать строки, не являющуюся частью словаря? ), Чтобы понять, почему …ˆ†=>это так "others=>".

Кевин Круйссен
источник