Ремонт диапазонов


30

Учитывая ввод списка положительных целых чисел, некоторые из которых заменены на 0, выведите список с отсутствующими числами, которые были заменены на 0замененные.

Характеристики входного списка:

  • Список всегда будет иметь длину не менее 2.

  • Давайте определим входной список как aи «исходный список» (то есть список до того, как числа были заменены на 0s) как b. Для любого n, a[n]либо b[n]или 0.

  • Для любого n, b[n]либо b[n-1] + 1или b[n-1] - 1. То есть числа в bбудут всегда меняться 1на каждый индекс по сравнению с его предыдущим. Первый элемент, конечно, освобожден от этого правила.

  • Для каждого прогона нулей в a(то есть, последовательные элементы заменен 0), с xпредставляющим индексом начала цикла и y представляющим конца, a[x-1]чтобы a[y+1]всегда быть либо только увеличение или уменьшение исключительно. Следовательно, будет только один возможный способ заполнить нули.

    • Это также означает, что ни первый, ни последний элемент массива не могут быть нулями.

Проще говоря, чтобы заполнить ряд нулей, просто замените его диапазоном от числа до до числа, следующего за ним. Например, ввод

1 2 0 0 0 6 7

должен выводить

1 2 3 4 5 6 7

Поскольку это , победит самый короткий код в байтах.

Тестовые случаи:

In                      Out
-----------------------------------------------------
1 0 0 0 5 6 0 4 0 0 1 | 1 2 3 4 5 6 5 4 3 2 1
7 6 0 0 3 0 0 0 7 0 5 | 7 6 5 4 3 4 5 6 7 6 5
1 0 3 0 5 0 3 0 5 0 7 | 1 2 3 4 5 4 3 4 5 6 7
14 0 0 0 0 0 0 0 0 23 | 14 15 16 17 18 19 20 21 22 23

Вместо того, чтобы 0наша программа могла принимать другое значение, например null?
Downgoat

@ Downgoat Нет, пропущенные номера должны быть указаны как 0.
Дверная ручка

Ответы:


15

JavaScript (ES6), 72 66 64 54 53 байта

Сохранено 12 байтов благодаря @Neil!

Сохранено 1 байт благодаря @IsmaelMiguel

a=>a.map((l,i)=>l?b=l:b+=a.find((q,r)=>r>i&&q)>b||-1)

Довольно хорошо для JavaScript.


Попробуйте онлайн (все браузеры работают)

объяснение

a=>  // Function with arg `a`
  a.map((l,i)=>  // Loop through input
    l?             // If nonzero
      b=l          // Set `b` to current number
    :a.find((q,r)=>r>i&q) // Otherwise look for the next nonzero number
     >b?           // If it's increased since nonzero last number   
       ++b:--b)    // Increasing? increase `b` (the previous nonzero number)
                   // otherwise decrease `b`

1
Я думаю, что a.find((q,r)=>r>i&&q)>b?++b:--bэто так же, какb+=a.find((q,r)=>r>i&&q)>b||-1
Исмаэль Мигель

@ IsmaelMiguel, это умно, спасибо!
Вниз

Пожалуйста. Я рад, что это сработало для вас.
Исмаэль Мигель

Я думаю, что вы можете заменить && на просто & (только что заметил, что у вас есть один & в объяснении и два в ответе)
Чарли Уинн


7

Haskell, 68 61 58 байт

g(a:b:r)=[a..b-1]++[a,a-1..b+1]++g(b:r)
g x=x
g.filter(>0)

Пример использования: g.filter(>0) $ [7,6,0,0,3,0,0,0,7,0,5]-> [7,6,5,4,3,4,5,6,7,6,5].

Как это работает: уберите нули с входа, затем позвоните g. Позвольте aбыть первым, а bзатем вторым элементом оставшегося списка. Объедините списки aсверху вниз b-1и снизу вверх (один из них будет пустым) и рекурсивный вызов с отброшенным. ab+1a

Редактировать: @Zgarb сохранил 3 байта. Благодарность!


6

Mathematica, 59 байт

#//.{a___,x_,0..,y_,b___}:>{a,##&@@Range[x,y,Sign[y-x]],b}&

Прецедент

%[{1,0,3,0,5,0,3,0,5,0,7}]
(* {1,2,3,4,5,4,3,4,5,6,7} *)

4

Perl, 47 45 44 39 37 байт

Включает +1 для -p

s%\S+%$p+=/\G(0 )+/?$'<=>$p:$&-$p%eg

Ожидает список на stdin. Пример: echo 1 0 3 0 1 | perl -p file.pl


Я вижу некоторые копии, вставленные здесь .. ;-) Хорошо сделано, кстати.
Кенни

3

Желе, 12 11 байт

ḢWW;ḟ0Ṫr¥\F

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

Альтернативная версия, 8 байт (не конкурирует)

К сожалению, popв последней версии, предшествующей этой проблеме , Jelly's не был приведен к повторяемости. Это было исправлено, и в текущей версии работает следующее.

ḟ0Ṫr¥\FḊ

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

Как это работает

ḢWW;ḟ0Ṫr¥\F  Main link. Input: A (list)

Ḣ            Pop the first element of A. Let's call it a.
 WW          Yield [[a]].
   ;         Concatenate with the popped A.
             This wraps the first element of A in an array.
    ḟ0       Filter; remove all zeroes.
        ¥    Create a dyadic chain:
      Ṫ        Pop the last element of the left argument.
       r       Call range on the popped element and the right argument.
         \   Reduce the modified A by this chain.
          F  Flatten the resulting list of ranges.

В альтернативной версии ḢWW;становится ненужным. Однако, поскольку первый элемент приводится к повторяемости перед извещением, он фактически не изменяется. Финал удаляет дубликат первого элемента.


3

Сетчатка, 39 34 31 байт

3 байта сохранены благодаря @Martin.

+`1(1*) (?= +((1)\1)?)
$0$1$3$3

Принимает ввод и выдает вывод в унарном виде.

Код итеративно заполняет каждое пустое место (0) previous_number - 1 + 2 * if_next_nonzero_number_bigger. previous_number - 1есть $1и if_next_nonzero_number_biggerесть $3.

С десятичным вводом / выводом код имеет длину 51 байт, как вы можете видеть в онлайн-интерпретаторе со всеми тестовыми примерами .


Вы можете сохранить другой байт, пропустив первый 1в предпросмотре.
Мартин Эндер

@ MartinBüttner Верно, отредактировано.
рандома

2

GNU Sed (с execрасширением, использующим bash), 61

Оценка включает в себя +1 для -rопции для sed.

:
s/( 0)+ /../
s/\w+..\w+/{&}/
s/.*/bash -c 'echo &'/e
/ 0/b
  • Найти прогоны 0s и заменить их..
  • Поставьте фигурные скобки вокруг номеров конечных точек, чтобы создать расширение bash-скобок, как {1..4}для локальных конечных точек. Прелесть расширений bash-скобок здесь в том, что сгенерированная последовательность всегда будет идти в правильном направлении, независимо от того, больше ли начало или конец.
  • Используйте eопцию sкоманды, чтобы вызвать bash, чтобы оценить это расширение скобки
  • Если 0найдены какие-либо другие s, вернитесь к началу.

Ideone.


2

Python 2, 195 111 байтов (спасибо, Алекс !)

t=input()
z=0
for i,e in enumerate(t):
 if e:
  while z:t[i-z]=e+z if l>e else e-z;z-=1
  l=e
 else:z+=1
print t

Входные данные: должны быть [list]целыми числами
Выходные данные: [list]целыми числами


Прости за это! Исправлена. Спасибо за внимание.
Вагели

Не стоит беспокоиться. Хорошее решение. :) Вы можете уменьшить его до 112 байт, используя то же самое, просто немного больше в гольфе. У нас также есть коллекция советов для игры в гольф на Python здесь .
Алекс А.

1

Perl, 85 82 байта

включает +1 для -p

s/(\d+)(( 0)+) (\d+)/$s=$1;$e=$4;$_=$2;$c=$s;s!0!$c+=$e<=>$s!eg;"$s$_ $e"/e&&redo

Ожидает список на stdin. Пример: echo 1 0 3 0 1 | perl -p file.pl.

Это использует вложенное регулярное выражение. Несколько читабельно:

s/(\d+)(( 0)+) (\d+)                  # match number, sequence of 0, number
 /
    $s=$1;                            # start number
    $e=$4;                            # end number
    $_=$2;                            # sequence of ' 0'
    $c=$s;                            # initialize counter with start number
    s!0! $c += $s <=> $e !eg          # replace all 0 with (in|de)cremented counter
    "$s$_ $e"                         # return replacement
 /e
&& redo                               # repeat until no more changes.

1

Python 2, 92 88 байт

(Удалена промежуточная переменная)

t=filter(bool,input())
print sum([range(o,p,cmp(p,o))for o,p in zip(t,t[1:])],[])+t[-1:]

1

Pyth, 17 байт

u+G+treGHHfTtQ[hQ

Как это работает:

u                 reduce
              [hQ     seed: the first element of input, in a list
                      iterable:
          tQ              all except the first element of input
        fT                remove if 0
                      lambda: G is the list to be returned, H is the current item
 +G                       append to return list
    reGH                  a range from the last element of the return list and the current item
   +                      concatenated with
        H                 the last item (this step forms a bidirectional inclusive list)

Другими словами: все нули удаляются из входных данных, затем исключительный диапазон вставляется между каждым элементом. Этот диапазон имеет нулевую длину для элементов, находящихся только на расстоянии друг от друга.



1

Vim: 231 команда клавиш

Обратите внимание, что любой ^ перед символом означает, что вы должны держать контроль при наборе этого символа

mbomayiwo^V^R"^V^V^V^X ^V^["sy0dd`a@f ^["bc0yiwo^V^V^V^X^V^R"^V^[0l@sa^V^V^V^A-^V^[0f-"ayhdd`a@i ^["dc0mbyiwo^V^R"Exe@b^V^[0fel"ty2ldd`b@t ^["ec0wmbyiwo@f @d^V^[@z ^["fc0"xyiwwmbyiwocw^V^V^V^Rx^V^V^V^[@a@i @e^V^[@z ^["ic0IB0 B^V^R" ^V^OWB0 ^V^OA B0^V^[0*w"tyiWdd`b@t ^["zd0dd`bAe^[0@e 

Шаги, чтобы вы могли запустить это тоже!

  1. Скопируйте строку в Vim
  2. Введите :s/\^V/<Ctrl-V><Ctrl-V>/gи нажмите ввод (две буквы должны дать вам синее ^ V)
  3. Введите :s/\^R/<Ctrl-V><Ctrl-R>/gи нажмите Enter (вы должны увидеть синий ^ Rs сейчас)
  4. Введите :s/\^X/<Ctrl-V><Ctrl-X>/gи нажмите ввод (вы должны увидеть синие ^ X сейчас)
  5. Введите :s/\^O/<Ctrl-V><Ctrl-O>/gи нажмите ввод
  6. Введите :s/\^A/<Ctrl-V><Ctrl-A>/gи нажмите ввод
  7. Введите :s/\^\[/<Ctrl-V><Ctrl-[>/gи нажмите enter (эта команда немного отличается, потому что мне нужно было выйти из [)
  8. Тип 0"yy$. Команда теперь хранится в регистре y
  9. Настройте ввод в строке и выполните с @y

Если кто-то знает лучший способ поделиться командой, пожалуйста, дайте мне знать. Я знаю, что это долго, но это лучшее, что я мог придумать.

Ввод, вывод

Входная строка должна быть одна на любой строке в файле. 1 0 0 4 3 0 0 0 7

Выходные данные просто перезапишут входную строку 1 2 3 4 3 4 5 6 7

объяснение

Алгоритм

  1. Начните с ненулевого числа, убедитесь, что это не последний номер
  2. Найти следующее ненулевое число
  3. Возьми их разницу. Если ответ отрицательный, вам нужно уменьшить значение, чтобы восстановить диапазон, в противном случае увеличить значение, чтобы восстановить диапазон.
  4. Вернитесь к первому символу и замените каждый ноль, увеличивая / уменьшая предыдущее число.
  5. Повторяйте, пока не дойдете до последнего символа

Используемые макросы

@e - Проверить конец. К последнему номеру будет добавлена ​​электронная почта. Если число под курсором имеет значок e в конце, удалите его и остановите выполнение. В противном случае начните цикл интерполяции с @b.

mbyiwo^R"Exe@b^[0fel"ty2ldd`b@t

@b - начать цикл интерполяции. Сохраните число под курсором для операции вычитания (@s), а затем найдите следующий ненулевой член (@f)

mayiwo^R"^V^X ^["sy0dd`a@f

@s - Сохраняет команду вычитания для использования в @d. Это просто (val)^Xгде (val)находится число в начале шага интерполяции. Это устанавливается командой @b.

@f - Найти следующий ненулевой член. Запишите текущее значение в безымянный регистр, затем напишите @f @dв следующей строке и запустите @z. Это повторит эту команду, если число равно нулю, и выполнит @d, если это не так.

wmbyiwo@f @d^[@z

@z - Условное выполнение, если безымянный регистр равен 0. Эта команда ожидает две команды в новой строке в формате command1 command2. Если безымянный регистр равен 0, command1выполняется, в противном случае command2выполняется. Обратите внимание, что ни одна из команд не может содержать пробелов.

 IB0 B^R" ^OWB0 ^OA B0^[0*w"tyiWdd`b@t`

@t - Временный регистр команд. Сохраняет различные команды в течение короткого времени перед их выполнением. Используется в основном в операторах if.

@d - определить направление интерполяции. Вычитает первое число в последовательности из числа под курсором (используя @s). Если результат отрицательный, интерполяция должна уменьшаться, поэтому ^ X сохраняется в @a. В противном случае мы должны увеличить значение, чтобы ^ A было сохранено в @a. Как только это будет сохранено, вернитесь к началу этого цикла интерполяции и запустите @i для фактической интерполяции.

yiwo^V^X^R"^[0l@sa^V^A-^[0f-"ayhdd`a@i

@a - магазины либо ^Aили ^Xдля увеличения или уменьшения на стадии интерполяции. Это устанавливается командой @d.

@i - интерполировать. Скопируйте номер в текущем местоположении в @x и перейдите к следующему номеру. Если это число равно нулю, замените его на @x и запустите @a, чтобы правильно изменить его вверх или вниз, затем повторите эту команду. Если число не ноль, мы достигли конца этого цикла интерполяции. Новый должен начинаться с этого номера в качестве начала, поэтому запустите @e, чтобы проверить конец, и снова запустите.

"xyiwwmbyiwocw^V^Rx^V^[@a@i @e^[@z

@x - регистр временного хранения. Используется в команде интерполяции (@i)

Сломать нажатия клавиш

mbo :Set b mark to current position and open a new line below to write macros
mayiwo^V^R"^V^V^V^X ^V^["sy0dd`a@f ^["bc0 :Write to @b and reset line

yiwo^V^V^V^X^V^R"^V^[0l@sa^V^V^V^A-^V^[0f-"ayhdd`a@i ^["dc0 :Write to @d and reset line

mbyiwo^V^R"Exe@b^V^[0fel"ty2ldd`b@t ^["ec0 :Write to @e and reset line

wmbyiwo@f @d^V^[@z ^["fc0 :Write to @f and reset line

"xyiwwmbyiwocw^V^V^V^Rx^V^V^V^[@a@i @e^V^[@z ^["ic0 :Write to @i and reset line

IB0 B^V^R" ^V^OWB0 ^V^OA B0^V^[0*w"tyiWdd`b@t ^["zd0 :Write to @z and reset line

dd`b :Delete this line and move cursor back to original line

Ae^[ :Append an e to the last number

0@e  :Move to the beginning of the line and run

0

Python 3.5, 159 байт

рекурсивное решение

def f(s):
 h=s[0]
 g=lambda s,h,v:h*(h[-1]==s[0])if len(s)==1else(g(s[1:],h+[h[-1]-v],-v)+g(s[1:],h+[h[-1]+v],+v))*(s[0]==0 or h[-1]==s[0])
 return g(s,[h],1)

Ungolfed

def f(s):
    h=s[0]
    def g(s,h,v):
        if len(s)==1:
            if h[-1]!=s[0]:
                r=[]
            else:
                r=h
        else:
            if s[0]==0:
                r=g(s[1:],h+[h[-1]+v],v)
            elif h[-1]!=s[0]:
                r=[]
            else:
                r=g(s[1:],h+[h[-1]-v],-v)+g(s[1:],h+[h[-1]+v],+v)
        return r
return g(s,[h],1)

В решении для гольфа я заменяю условия, используя тот факт, что h*True=hиh*False=[]

Результат

>>> f([7, 6, 0, 0, 3, 0, 0, 0, 7, 0, 5])
[7, 6, 5, 4, 3, 4, 5, 6, 7, 6, 5]


0

MATLAB, 39 38 37 байт

@(a)interp1(find(a),a(a>0),find(a/0))

Анонимная функция, которая линейно интерполирует между точками в a. find(a)является массивом индексов ненулевых элементов в aи a(a>0)являются положительными значениями. Сохранено 1 байт благодаря предложению друга, >а не ~=.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.