Відремонтуйте діапазони


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 Ні, пропущені номери повинні бути вказані як 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 це розумно, дякую!
Пуховик

Ласкаво просимо. Я радий, що це склалося для тебе.
Ісмаїл Мігель

Я думаю, ви можете замінити && на просто & (Щойно помітив, що у вас є одне & в поясненні та два у відповіді)
Charlie Wynn


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і aвниз до b+1(один з них буде порожнім) та рекурсивний дзвінок зі aскинутим.

Редагувати: @ Zgarb збережено 3 байти. Спасибі!


6

Математика, 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. Приклад: відлуння 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варіант сіт.

:
s/( 0)+ /../
s/\w+..\w+/{&}/
s/.*/bash -c 'echo &'/e
/ 0/b
  • Знайдіть запуски 0s та замініть їх..
  • Поставте фігурні дужки навколо цифр кінцевих точок, щоб створити розширення дугової фігури, як {1..4}для місцевих кінцевих точок. Краса розширень баш-брекетів полягає в тому, що створена послідовність завжди буде вестись у правильному напрямку, незалежно від того, чи більший початок чи кінець.
  • Використовуйте eопцію sкоманди, щоб викликати bash для оцінки цього розширення дужок
  • Якщо 0знайдено більше s, поверніться до початку.

Ідеон.


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]з ints
Вихід: [list]of ints


Вибач за це! Виправлено. Дякую за голову вгору
vageli

Не хвилюйтесь. Приємне рішення. :) Ви можете скористатися цим на 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

Піт, 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і натисніть клавішу Enter (два s повинні дати вам синій ^ V)
  3. Введіть :s/\^R/<Ctrl-V><Ctrl-R>/gі натисніть клавішу Enter (ви повинні побачити синій ^ Rs зараз)
  4. Введіть :s/\^X/<Ctrl-V><Ctrl-X>/gі натисніть клавішу Enter (ви повинні побачити синій ^ Xs зараз)
  5. Введіть :s/\^O/<Ctrl-V><Ctrl-O>/gі натисніть клавішу Enter
  6. Введіть :s/\^A/<Ctrl-V><Ctrl-A>/gі натисніть клавішу Enter
  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. Якщо число під курсором має 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)

Безумовно

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.