Заполните возрастающую последовательность как можно большим количеством цифр


29

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

Например, 1, 1, 2, 4, 5, 5, 5, 8, 10, 11, 14, 14монотонно увеличивается.

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

Там может быть несколько способов сделать это. Любое действительно.

Выведите итоговый список.

Например , если вход

?, 1, ?, 1, 2, ?, 4, 5, 5, 5, ?, ?, ?, ?, 8, 10, 11, ?, 14, 14, ?, ?

гарантируется, что без пустых мест список будет монотонно увеличиваться

1, 1, 2, 4, 5, 5, 5, 8, 10, 11, 14, 14

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

Одно задание , которое является не действительным является

1, 1, 1, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 8, 10, 11, 14, 14, 14, 14, 14

потому что, хотя оно не уменьшается, у него есть только одно уникальное целое число, а не входное, а именно 3.

В этом примере можно вставить шесть уникальных натуральных чисел и сохранить список неубывающим.
Пара возможных способов:

1, 1, 1, 1, 2, 3, 4, 5, 5, 5, 6, 7, 8, 8, 8, 10, 11, 12, 14, 14, 15, 16

1, 1, 1, 1, 2, 3, 4, 5, 5, 5, 5, 6, 6, 7, 8, 10, 11, 13, 14, 14, 20, 200

Любой из этих (и многих других) будет правильным выводом.

Все пустые места должны быть заполнены.

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

Ноль не является положительным целым числом и никогда не должен вставляться.

На месте ?вы можете использовать любое приемлемое значение, которое не является положительным целым числом, например 0, -1, null, False, или "".

Самый короткий код в байтах побеждает.

Больше примеров

[input]
[one possible output] (a "*" means it is the only possible output)

2, 4, 10
2, 4, 10 *

1, ?, 3
1, 2, 3 *

1, ?, 4
1, 2, 4

{empty list}
{empty list} *

8
8 *

?
42

?, ?, ?
271, 828, 1729

?, 1
1, 1 *

?, 2
1, 2 *

?, 3
1, 3

45, ?
45, 314159265359

1, ?, ?, ?, 1
1, 1, 1, 1, 1 *

3, ?, ?, ?, ?, 30
3, 7, 10, 23, 29, 30 

1, ?, 2, ?, 3, ?, 4
1, 1, 2, 3, 3, 3, 4

1, ?, 3, ?, 5, ?, 7
1, 2, 3, 4, 5, 6, 7 *

1, ?, 3, ?, 5, ?, ?, 7
1, 2, 3, 4, 5, 6, 7, 7

1, ?, ?, ?, ?, 2, ?, ?, ?, ?, 4, ?, 4, ?, ?, 6
1, 1, 1, 1, 1, 2, 3, 4, 4, 4, 4, 4, 4, 5, 6, 6

98, ?, ?, ?, 102, ?, 104
98, 99, 100, 101, 102, 103, 104 *

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

@StewieGriffin Вы можете предположить, что значения и длина списка, как обычно, ниже int максимумов. Я только имел в виду, что в конце нормально вставлять очень большие целые числа, если так работает ваш алгоритм.
Увлечения Кальвина

Ответы:


11

Haskell , 41 байт

fберет список и возвращает список с 0, представляющим ?s.

f=scanr1 min.tail.scanl(#)0
m#0=m+1
_#n=n

По сути, первый список сканирования слева, заменяя 0 на один больше, чем предыдущий элемент (или 0 в начале); затем отсканируйте справа, уменьшив слишком большие элементы, чтобы они равнялись значению справа.

Попробуйте онлайн! (с оберткой для преобразования ?s.)


4

Mathematica, 84 байта

Rest[{0,##}&@@#//.{a___,b_,,c___}:>{a,b,b+1,c}//.{a___,b_,c_,d___}/;b>c:>{a,c,c,d}]&

Функция Pure принимает список в качестве аргумента, где пустые места обозначаются Null(как в {1, Null, Null, 2, Null}) или удаляется вообще (как в {1, , , 2, }), и возвращает подходящий список (в данном случае, {1, 2, 2, 2, 3}).

Оказывается, я использую тот же алгоритм, что и в ответе Оркена Йохансена на Haskell : сначала замените каждый Nullна единицу больше, чем число слева ( //.{a___,b_,,c___}:>{a,b,b+1,c}), а затем замените слишком большое число числом справа ( //.{a___,b_,c_,d___}/;b>c:>{a,c,c,d}). Чтобы разобраться с возможными Nulls в начале списка, мы начинаем с добавления a 0( {0,##}&@@#), выполняем алгоритм, затем удаляем initial 0( Rest).

Да, я выбрал Nullвместо Xили что-то подобное, чтобы сохранить буквально один байт в коде (тот, который в противном случае был бы между запятыми b_,,c___).


Хм, предпочитаешь 1 ты говоришь? Я использовал 0, из-за таких вещей, как ?, 2. Я подозреваю, что вы бы тогда производили 2, 2вместо правильных 1, 2.
Эрджан Йохансен,

Отличный момент! К счастью, это легко исправить.
Грег Мартин,

3

С 160

Это никогда не победит, но:

#define p(x)printf("%d ",x);
i=1,l=0,m=0,n;main(c,v)char**v;{for(;i<c;i++)if(*v[i]==63)m++;else{for(n=atoi(v[i]);m>0;m--)p(l<n?++l:n)p(l=n)}for(;m>0;m--)p(++l)}

Он берет список из аргументов командной строки.



3

05AB1E , 31 23 13 байт

Сохранено 10 байтов благодаря Grimy

ε®X:D>U].sR€ß

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

объяснение

ε      ]       # apply to each number in input
 ®X:           # replace -1 with X (initially 1)
    D>U        # store current_number+1 in X
        .s     # get a list of suffixes
          R    # reverse
           ۧ  # take the minimum of each

Почему это печатает только часть вывода? В вашем примере TIO первая 1 отсутствует.
Fatalize

Я знаю, что это было какое-то время, и, возможно, его можно сыграть в гольф еще, но -3 байта с некоторыми простыми играми: оба }}могут ]сэкономить 2 байта; и õ-)Rможно )˜Rсохранить дополнительный байт.
Кевин Круйссен

2
@KevinCruijssen: Действительно, это могло бы быть :)
Emigna

1
Это все еще может! 16 , 15 , 13 .
Гримми

@ Грими: Вау, спасибо! Этот трюк с суффиксом был действительно умным!
Эминья

2

Пип , 25 23 21 байт

Y{Y+a|y+1}MgW PMNyPOy

Принимает ввод как несколько разделенных пробелом аргументов командной строки. Выводит список результатов по одному номеру в каждой строке. Попробуйте онлайн! (Я выдумал несколько аргументов командной строки, потому что было бы больно добавлять 25 аргументов в TIO, но это работает так, как рекламируется).

объяснение

Мы продолжаем в два прохода. Сначала мы заменяем каждый прогон ?s во входных данных последовательностью, начинающейся с предыдущего числа в списке и увеличивающейся на единицу каждый раз:

? 1 ? 1 2 ? 4 5 5 5 ? ? ? ? 8 10 11 ?  14 14 ?  ?
1 1 2 1 2 3 4 5 5 5 6 7 8 9 8 10 11 12 14 14 15 16

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

                      y is initially "", which is 0 in numeric contexts
                      Stage 1:
 {       }Mg           Map this function to list of cmdline args g:
   +a                  Convert item to number: 0 (falsey) if ?, else nonzero (truthy)
     |                 Logical OR
      y+1              Previous number +1
  Y                    Yank that value into y (it is also returned for the map operation)
Y                      After the map operation, yank the whole result list into y
                      Stage 2:
            W          While loop, with the condition:
               MNy      min(y)
              P         printed (when y is empty, MN returns nil, which produces no output)
                  POy  Inside the loop, pop the leftmost item from y

2

Python 2 с NumPy, 163 байта

Сохранено 8 байт благодаря @wythagoras

Нули используются для обозначения пустых мест

import numpy
l=[1]+input()
z=numpy.nonzero(l)[0]
def f(a,b):
 while b-a-1:a+=1;l[a]=l[a-1]+1;l[a]=min(l[a],l[b])
i=1
while len(z)-i:f(z[i-1],z[i]);i+=1
print l[1:]

Более читабельно с комментариями:

import numpy
l=[1]+input()           # add 1 to the begining of list to handle leading zeros
z=numpy.nonzero(l)[0]   # get indices of all non-zero values
def f(a,b):             # function to fill gap, between indices a and b
    while b-a-1:
        a+=1
        l[a]=l[a-1]+1   # set each element value 1 larger than previous element
        l[a]=min(l[a],l[b])   # caps it by value at index b
i=1
while len(z)-i:       
    f(z[i-1],z[i])      # call function for every gap
    i+=1
print l[1:]             # print result, excluding first element, added at the begining

1
Несколько улучшений: if l[a]>l[b]:l[a]=l[b]может быть, l[a]=min(l[a],l[b])и тогда это может быть на линии до этого. Кроме того, это означает, что всю строку можно поставить после while. И я думаю, l=input()и l=[1]+lможет быть l=[1]+input()(Кроме того, в целом: если вы используете два уровня отступа, вы можете использовать пробел и табуляцию вместо пробела и двух пробелов в Python 2 (см. Codegolf.stackexchange.com/a/58 ) )
wythagoras

1
Также рядом с последней строкой может находиться время, len(z)-i:f(z[i-1],z[i]);i+=1когда начинается с i = 1.
wythagoras

@wythagoras Спасибо, хорошие советы. Я добавил это к коду
Мертвый Опоссум

Хорошо, но это всего 163 байта.
Витагор

@wythagoras О, я забыл обновить счетчик байтов
Мертвый Опоссум

1

PHP, 95 77 71 69 68 байт

for($p=1;$n=$argv[++$i];)echo$p=$n>0?$n:++$p-in_array($p,$argv)," ";

принимает входные данные из аргументов командной строки, печатает разделенный пробелами список. Беги с -nr.

сломать

for($p=1;$n=$argv[++$i];)   # loop through arguments
    echo$p=                     # print and copy to $p:
    $n>0                            # if positive number
        ?$n                             # then argument
        :++$p                           # else $p+1 ...
            -in_array($p,$argv)         # ... -1 if $p+1 is in input values
    ," ";                       # print space

$nверно для любой строки, кроме пустой строки и "0".
$n>0верно для положительных чисел - и строк, содержащих их.


1

Perl 6 , 97 байт

{my $p;~S:g/(\d+' ')?<(('?')+%%' ')>(\d*)/{flat(+($0||$p)^..(+$2||*),(+$2 xx*,($p=$2)))[^+@1]} /}

Входные данные - это либо список значений, либо строка, разделенная пробелом, где ?используется для замены значений, подлежащих замене.

Выход - строка, разделенная пробелом, с завершающим пробелом.

Попытайся

Expanded:

{                       # bare block lambda with implicit parameter 「$_」

    my $p;              # holds the previous value of 「$2」 in cases where
                        # a number is sandwiched between two replacements

    ~                   # stringify (may not be necessary)
    S                   # replace
    :global
    /
        ( \d+ ' ' )?    # a number followed by a space optionally ($0)

        <(              # start of replacement

          ( '?' )+      # a list of question marks
          %%            # separated by (with optional trailing)
          ' '           # a space

        )>              # end of replacement

        (\d*)           # an optional number ($2)

    /{                  # replace with the result of:

        flat(

          +( $0 || $p ) # previous value or 0
          ^..           # a range that excludes the first value
          ( +$2 || * ), # the next value, or a Whatever star

          (
            +$2 xx *,   # the next value repeated endlessly

            ( $p = $2 ) # store the next value in 「$p」
          )

        )[ ^ +@1 ]      # get as many values as there are replacement chars
    } /                 # add a space afterwards
}

Я не знаю Perl 6, но в Perl 5 вы можете использовать $"вместо того, ' 'чтобы брить байт. Это работает здесь?
msh210

@ msh210 Почти все эти переменные либо пропали, либо имеют более длинные имена. О единственном, который все еще существует и имеет ту же цель $!. ( $/существует, но используется для $1$/[1]и $<a>$/{ qw< a > })
Брэд Гилберт b2gills

1

JavaScript (ES6), 65 байт

a=>a.map(e=>a=e||-~a).reduceRight((r,l)=>[r[0]<l?r[0]:l,...r],[])

Потому что я хотел использовать reduceRight. Объяснение: Параметр mapзаменяет каждое ложное значение на единицу больше, чем предыдущее значение, затем выполняет reduceRightобратное выполнение с конца, гарантируя, что никакое значение не превысит следующее значение.


1

Q, 63 байта

{1_(|){if[y>min x;y-:1];x,y}/[(|){if[y=0;y:1+-1#x];x,y}/[0,x]]}

По сути тот же алгоритм, что и в ответе Хаскелла Эрджана Йохансена .

  • Предполагает? = 0
  • Вставляет 0 в начале массива в случае? в начале.
  • Сканирует массив, заменяя 0 на 1 + предыдущий элемент.
  • Обращает массив и снова сканирует, заменяя элементы больше, чем предыдущий элемент, на предыдущий элемент.
  • Переворачивает и обрезает первый элемент (добавленный 0 с начала).

Использование min vs last использовалось для сохранения одного байта, поскольку можно предположить, что последний элемент будет элементом min с учетом сортировки массива по убыванию.


Классный ответ, добро пожаловать на сайт! :)
DJMcMayhem

1

TI-Basic (TI-84 Plus CE), 81 байт

not(L1(1))+L1(1→L1(1
For(X,2,dim(L1
If not(L1(X
1+L1(X-1→L1(X
End
For(X,dim(L1)-1,1,-1
If L1(X)>L1(X+1
L1(X+1→L1(X
End
L1

Простой порт ответа Хаскелла Эрджана Йохансена на TI-Basic. Использует 0 как нулевое значение. Принимает данные от L 1 .

Объяснение:

not(L1(1))+L1(1→L1(1 # if it starts with 0, change it to a 1
For(X,2,dim(L1     # starting at element 2:
If not(L1(X              # if the element is zero
1+L1(X-1→L1(X            # change the element to one plus the previous element
End
For(X,dim(L1)-1,1,-1 # starting at the second-last element and working backwards
If L1(X)>L1(X+1           # if the element is greater than the next
L1(X+1→L1(X               # set it equal to the next
End
L1                   # implicitly return

1

Java 8, 199 164 байта

a->{for(int l=a.length,n,j,x,i=0;i<l;)if(a[i++]<1){for(n=j=i;j<l;j++)if(a[j]>0){n=j;j=l;}for(j=i-3;++j<n-1;)if(j<l)a[j+1]=j<0?1:a[j]+(l==n||a[n]>a[j]|a[n]<1?1:0);}}

Изменяет массив ввода вместо того, чтобы возвращать новый для сохранения байтов.
Использует 0вместо ?.

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

Объяснение:

a->{                      // Method with integer-array parameter and no return-type
  for(int l=a.length,     //  Length of the input-array
      n,j,x,              //  Temp integers
      i=0;i<l;)           //  Loop `i` over the input-array, in the range [0, length):
    if(a[i++]<1){         //   If the `i`'th number of the array is 0:
                          //   (And increase `i` to the next cell with `i++`)
      for(n=j=i;          //    Set both `n` and `j` to (the new) `i`
          j<l;j++)        //    Loop `j` in the range [`i`, length):
        if(a[j]>0){       //     If the `j`'th number of the array is not 0:
          n=j;            //      Set `n` to `j`
          j=l;}           //      And set `j` to the length to stop the loop
                          //    (`n` is now set to the index of the first non-0 number 
                          //     after the `i-1`'th number 0)
      for(j=i-3;++j<n-1;) //    Loop `j` in the range (`i`-3, `n-1`):
        if(j<l)           //     If `j` is still within bounds (smaller than the length)
          a[j+1]=         //      Set the `j+1`'th position to:
            j<0?          //       If `j` is a 'position' before the first number
             1            //        Set the first cell of the array to 1
            :             //       Else:
             a[j]+        //        Set it to the `j`'th number, plus:
              (l==n       //        If `n` is out of bounds bounds (length or larger)
               ||a[n]>a[j]//        Or the `n`'th number is larger than the `j`'th number
               |a[n]<1?   //        Or the `n`'th number is a 0
                1         //         Add 1
               :          //        Else:
                0);}}     //         Leave it unchanged by adding 0


0

JavaScript (ES6), 59

Функция с целочисленным массивом в качестве входных данных. Пустые места отмечены0

a=>a.map((v,i)=>v?w=v:(a.slice(i).find(x=>x)<=w?w:++w),w=0)

Тест

var F=
a=>a.map((v,i)=>v?w=v:(a.slice(i).find(x=>x)<=w?w:++w),w=0)

;[[2, 4, 10]
,[1, 0, 3]
,[1, 0, 4]
,[]
,[8]
,[0]
,[0, 0, 0]
,[0, 1]
,[0, 2]
,[0, 3]
,[45, 0]
,[1, 0, 0, 0, 1]
,[3, 0, 0, 0, 0, 30]
,[1, 0, 2, 0, 3, 0, 4]
,[1, 0, 3, 0, 5, 0, 7]
,[1, 0, 3, 0, 5, 0, 0, 7]
,[1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 4, 0, 4, 0, 0, 6]
,[98, 0, 0, 0, 102, 0, 104]]
.forEach(a=>{
  console.log(a+'\n'+F(a))
})


0

C # (.NET Core) , 182 байта

Использую ту же стратегию, что и Орджан Йохансен.

Использует 0 в списке ввода, чтобы отметить неизвестную переменную.

l=>{if(l[0]<1)l[0]=1;int j;for(j=0;j<l.Length;j++)l[j]=l[j]==0?l[j-1]+1:l[j];for(j=l.Length-2;j>=0;j--)l[j]=l[j]>l[j+1]?l[j+1]:l[j];foreach(var m in l) System.Console.Write(m+" ");};

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


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