Заповніть порожні місця, заповнивши порожні заготовки


10

Напишіть функцію (таку як placeAt), яка приймає масив невід’ємних цілих чисел та індекс, який є негативним цілим числом. Він повинен поставити 1 у заданому індексі, можливо, змістивши інші записи на одне місце, щоб звільнити це місце, а 0 - на порожні місця.

  • Якщо запис у потрібному індексі дорівнює 0, заповніть його 1.
  • В іншому випадку шукайте найближчий 0 ліворуч від індексу. Змініть записи на одне місце ліворуч на 0, щоб звільнити місце, а потім заповніть індекс 1.
  • Якщо зліва немає 0, зробіть те ж саме, рухаючись праворуч.
  • Якщо жодне з можливих (тобто якщо немає 0), поверніть масив без змін.

Елементи є 0-індексованими. Ім'я функції може бути будь-яким, що ви хочете.

Приклади:

(Букви означають будь-які додатні цілі значення.)

[a, b, 0, c, d, 0] placeAt 2    // output [a, b, 1, c, d, 0]    place 2 is 0, just fill
[a, b, 0, c, d, 0] placeAt 3    // output [a, b, c, 1, d, 0]    place 3 is filled, shift items left
[a, b, 0, c, d, 0] placeAt 0    // output [1, a, b, c, d, 0]    place 0 is filled, can't shift left, shift items right
[a, b, 0, c, d, 0] placeAt 1    // output [a, 1, b, c, d, 0]    place 1 is filled, can't shift left, shift items right
[0, a, b, 0, c, d, 0] placeAt 2 // output [a, b, 1, 0, c, d, 0] place 2 is filled, shift items left
[0, a, b, 0, c, d, 0] placeAt 4 // output [0, a, b, c, 1, d, 0] place 4 is filled, shift items left (notice you keep shifting up until a 0)
[0, 2, 0, 2] placeAt 3          // output [0, 2, 2, 1]          place 3 is filled, shift items left

Це виклик для гольфу з кодом. Найкоротший запис в кінці 9 днів виграє.


4
Як ви знаєте, чи слід зрушувати вліво або вправо, коли це можливо обоє? Крім того, що робити, якщо його немає 0?
xnor

Бо [0, 2, 0, 2] placeAt 3чи законно це робити [2, 0, 2, 1]? Чи потрібний код, щоб насправді називатися функцією placeAt? Зауважте, що деякі мови не мають точно функцій. "Киньте виняток" може також не стосуватися деяких мов; Я б запропонував дозволити вихід, що вказує на помилку.
xnor

Чи може масив мати негативні значення?
Кейд

Я на 99% впевнений, що я розумію наміри ОП з правилами цього виклику, тому я реорганізував посаду (зараз у черзі) і спробую відповісти на запитання. eguneys, ви можете виправити будь-яку з моїх відповідей, якщо це буде потрібно.
ETHproductions

@xnor Зсув ліворуч завжди віддає перевагу зміщенню праворуч. Якщо немає 0, просто поверніть початковий масив. Крім того, [2, 0, 2, 1]це не є законним результатом, оскільки ви завжди повинні зміщувати якомога менше елементів, і ви можете називати функцію все, що завгодно.
ETHproductions

Відповіді:


4

JavaScript (ES6), 85

Тестуйте запуск фрагмента в будь-якому веб-переглядачі, сумісному з EcmaScript 6 (особливо це не Chrome не MSIE. Я тестував на Firefox, Safari 9 може піти)

(Я знайшов це, не дивлячись на жоден з інших відповідей, тепер я бачу, що він дуже схожий на каток. І все-таки досить коротший. Напевно, я не отримаю багато відгуків за цей)

F=(a,p,q=~a.lastIndexOf(0,p)||~a.indexOf(0))=>(q&&(a.splice(~q,1),a.splice(p,0,1)),a)

// Ungolfed
U=(a,p)=>{
  q = a.lastIndexOf(0, p)
  if (q < 0) q = a.indexOf(0)
  if (q >= 0) {
    a.splice(q, 1)
    a.splice(p, 0, 1)
  }
  return a
}  

// TEST
out=x=>O.innerHTML+=x+'\n';

[ [['a', 'b', 0, 'c', 'd', 0], 2, ['a', 'b', 1, 'c', 'd', 0]] // place 2 is 0, just fill
, [['a', 'b', 0, 'c', 'd', 0], 3, ['a', 'b', 'c', 1, 'd', 0]] // place 3 is filled, shift items left
, [['a', 'b', 0, 'c', 'd', 0], 0, [1, 'a', 'b', 'c', 'd', 0]] // place 0 is filled, can't shift left, shift items right
, [['a', 'b', 0, 'c', 'd', 0], 1, ['a', 1, 'b', 'c', 'd', 0]] // place 1 is filled, can't shift left, shift items right
, [[0, 'a', 'b', 0, 'c', 'd', 0], 2, ['a', 'b', 1, 0, 'c', 'd', 0]] // place 2 is filled, shift items left
, [[0, 'a', 'b', 0, 'c', 'd', 0], 4, [0, 'a', 'b', 'c', 1, 'd', 0]] // place 4 is filled, shift items left (notice you keep shifting up until a 0)
, [['a', 'b', 'c', 'd'], 2, ['a', 'b', 'c', 'd']] // impossible
, [[0, 2, 0, 2], 3, [0, 2, 2, 1]]] // place 3 is filled, shift items left
.forEach(t=>{
  i=t[0]+''
  r=F(t[0],t[1])+''
  k=t[2]+''
  out('Test ' + (r==k?'OK':'Fail') +'\nInput: '+i+' '+t[1]+'\nResult:'+r+'\nCheck: '+k+'\n')
})
<pre id=O></pre>


+1, тому що я щойно дізнався про оператор комами, а за побиття
rink.attendant.6

@ rink.attendant.6, але використання &&, щоб приєднатися до цього splice, краще, ніж моя кома
edc65

3

Джулія, 122 байти

Просто наївна реалізація специфікації, щоб розпочати справи.

f(x,i)=(i+=1;x[i]==0?(x[i]=1):i>2&&x[i-1]==0?(x[i-1]=x[i];x[i]=1):i<length(x)-1&&x[i+1]==0?(x[i+1]=x[i];x[i]=1):error();x)

Безголівки:

function placeAt(x::Array, i::Int)
    # Make i 1-indexed
    i += 1

    # Shift and modify the array as necessary
    if x[i] == 0
        x[i] = 1
    elseif i > 2 && x[i-1] == 0
        x[i-1], x[i] = x[i], 1
    elseif i < length(x)-1 && x[i+1] == 0
        x[i+1], x[i] = x[i], 1
    else
        error()
    end

    # Return the modified array
    x
end

1

JavaScript (ES6), 98 байт

Приблизно такий самий підхід, як і моя відповідь CoffeeScript, але я коротко замикаюсь на крайнє місце, щоб зберегти returnтвердження:

f=(a,x)=>(~($=a.lastIndexOf(0,x))||~(_=a.indexOf(0,x)))&&a.splice(~$?$:_,1)&&a.splice(x,0,1)&&a||a

Пояснення

Щоб легше пояснити, я трохи змінив код:

// Declare function f with two arguments: array and position
f = (a, x) => {
    // Take the part of the array from beginning to x and find the last 0
    $ = a.lastIndexOf(0, x)

    // Find the first 0 after position x
    _ = a.indexOf(0, x);

    // indexOf returns -1 if they aren't found
    // ~1 == 0 so I am checking if either $ or _ is truthy (zeros were found)
    if (~$ || ~_)
       // If zeros were found in the left, use that.
       // Otherwise use the found zero in the right.
       // Delete it from the array
       // Array.prototype.splice will return an array which evaluates to truthy
       // and continues execution with the &&
       // Insert value 1 at position x, deleting 0 elements
       // The last value is returned
       return a.splice(~$ ? $ : _, 1) && a.splice(x, 0, 1) && a
    else
       // No zeros were found so just return the original
       // In the golfed code the if would have evaluated to false to cut into the || part
       return a
}

Ось деяка інформація щодо оцінки короткого замикання JS.

Демо

На даний момент ця демонстрація працює лише у Firefox та Edge завдяки використанню ES6:

f=(a,x)=>(~($=a.lastIndexOf(0,x))||~(_=a.indexOf(0,x)))&&a.splice(~$?$:_,1)&&a.splice(x,0,1)&&a||a

// Snippet stuff
console.log = x => O.innerHTML += x + '\n';

console.log(f(['a', 'b', 0, 'c', 'd', 0], 2))
console.log(f(['a', 'b', 0, 'c', 'd', 0], 3))
console.log(f(['a', 'b', 0, 'c', 'd', 0], 0))
console.log(f([0, 'a', 'b', 0, 'c', 'd', 0], 2))
console.log(f([0, 'a', 'b', 0, 'c', 'd', 0], 4))
console.log(f(['a', 'b', 0, 'c', 'd', 0], 2))
console.log(f(['a', 'b', 0, 'c', 'd', 0], 1))
<pre id=O></pre>


Як це працює, ви можете пояснити, будь ласка.
eguneys

@eguneys Додано пояснення
rink.attendant.6

це не працює дляf(['a', 'b', 0, 'c', 'd', 0], 2)
eguneys

@eguneys Виправлено. Я забув, що CoffeeScript автоматично додає його під час використання їх скорочення [a..b].
rink.attendant.6

не працює дляf(['a', 'b', 0, 'c', 'd', 0], 1)
eguneys

1

Рубін, 208 байт

def f(a,i)
  x=a.take(i).rindex(0);y=a[i+1..-1].index(0)
  if a[i]==0
    a[i]=1
  elsif !x.nil?
    a.delete_at(x);a.insert(i,1)
  elsif !y.nil?
    a.delete_at(y+i+1);a.insert(i,1)
  end
  a
end

Ласкаво просимо до PPCG! Деякі прості поради щодо гольфу для Рубі: вам не потрібні відступи, тому ви зможете позбутися всіх просторів. Тоді вам також не знадобляться крапки з комою, тому що один новий рядок - це стільки ж байтів. Виклики методу в кінці оператора не потребують дужок, тому ви можете це робити, наприклад .rindex 0, зберігаючи один байт кожен раз. Ви можете також зберегти деякі байти , використовуючи процедурний замість методу, який навіть не повинні бути названі: ->a,i{...}. Якщо / elsif / elsif, ймовірно, можна скоротити за допомогою вкладеного потрійного оператора ...?...:...?...:....
Мартін Ендер

Дуже дякую за добру пораду. Я загляну в це і побачу, що я можу зробити.
ремісничий день

1

Haskell, 119 байт

e=elem 0
r=reverse
f=(g.).splitAt
g(a,y@(x:b))|e(x:a)=r(h(x:r a)1)++b|e y=a++h y 1|1<2=a++y 
h(0:r)n=n:r
h(a:r)n=n:h r a

Приклад використання:

*Main> mapM_ (print.uncurry f) [ 
                (2,[2,3,0,4,5,0]),
                (3,[2,3,0,4,5,0]),
                (0,[2,3,0,4,5,0]),
                (1,[2,3,0,4,5,0]),
                (2,[0,2,3,0,4,5,0]),
                (4,[0,2,3,0,4,5,0]),
                (3,[0,2,0,2]),
                (2,[2,3,4,5])  ]
[2,3,1,4,5,0]
[2,3,4,1,5,0]
[1,2,3,4,5,0]
[2,1,3,4,5,0]
[2,3,1,0,4,5,0]
[0,2,3,4,1,5,0]
[0,2,2,1]
[2,3,4,5]

Як це працює: Розбийте список вводу в заданій позиції на ліву частину a, елемент на саму позицію xта праву частину b. Якщо є 0в a++x, звільніть місце спочатку 0в звороті a++x. Якщо є 0в x++b, звільніть там місце. Якщо цього немає 0, комбінуйте всі частини без змін, щоб знову отримати оригінальний список.


0

CoffeeScript, 96 байт

f=(a,_)->a.splice((if~($=a.lastIndexOf 0,_)then $ else a.indexOf 0),1);a.splice(_,0,1)if 0in a;a

0

Python 2, 102 байти

def f(a,i):
 x=(a[i-1::-1]+a[i:]+[0]).index(0)
 if x<len(a):del a[(x,i-x-1)[x<i]];a[i:i]=[1]
 return a

Обчислює індекс нуля, що підлягає вилученню, об'єднуючи список, перевернутий до індексу вставки, з частиною після індексу у звичайному порядку, потім знаходячи індекс першого нуля. Нуль додається в кінці, щоб уникнути ValueErrorвинятків, коли нуль не знайдено. Потім просто видаліть, вставіть і поверніть.


0

R, 87 байт

f=function(a,i)if(0%in%a)append(a[-abs(min((b=which(a==0))*(1-(b<=i+1)*2)))],1,i)else a

Пояснення

function(a,i)
if(0%in%a)                      # as long as a 0 exists
    append(                     # append 1 after i
        a[
          -abs(                 # remove absolute of min index
            min(                # minimum of adjusted index
              (b=which(a==0))*  # index of all 0's
              (1-(b<=i+1)*2)    # multiple -1 if <= i
              )
            )
        ]
        ,1
        ,i
    )
else                            # otherwise return untouched
    a

Тести

> f(c(2, 3, 0, 4, 5, 0) , 2)   
[1] 2 3 1 4 5 0
> f(c(2, 3, 0, 4, 5, 0) , 3)   
[1] 2 3 4 1 5 0
> f(c(2, 3, 0, 4, 5, 0) , 0)   
[1] 1 2 3 4 5 0
> f(c(2, 3, 0, 4, 5, 0) , 1)   
[1] 2 1 3 4 5 0
> f(c(0, 2, 3, 0, 4, 5, 0) , 2)
[1] 2 3 1 0 4 5 0
> f(c(0, 2, 3, 0, 4, 5, 0) , 4)
[1] 0 2 3 4 1 5 0
> f(c(0, 2, 0, 2) , 3)         
[1] 0 2 2 1
> 

0

C #, 265 байт

Гольф (265 персонажів)

static void placeAt(String[]Q,int P){int I;if(Q[P]=="0"){Q[P]="1";}else{I=Array.IndexOf(Q,"0");if(I>=0){if(I<P){for(int i=I;i<=P;i++){Q[i]=(i==P)?"1":Q[i+1];}}else if(I>P){for(int i=I;i>=P;i--){Q[i]=(i==P)?"1":Q[i-1];}}}}foreach(String s in Q)Console.Write(s+" ");}

З білими пробілами та відступами

static void placeAt(String[] Q, int P)
    {
        int I;

        if(Q[P] == "0")
        {
            Q[P] = "1";
        }
        else
        {
            I = Array.IndexOf(Q, "0");
            if (I >= 0)
            {
                if (I < P)
                {
                    for (int i = I; i <= P; i++)
                    {
                        Q[i] = (i == P) ? "1" : Q[i + 1];
                    }
                }
                else if (I > P)
                {
                    for (int i = I; i >= P; i--)
                    {
                        Q[i] = (i == P) ? "1" : Q[i - 1];
                    }
                }
            }
        }

        foreach (String s in Q)
            Console.Write(s + " ");
    }

Ціла програма

using System;

class FillZero
{
    static void placeAt(String[] Q, int P)
    {
        int I;

        if(Q[P] == "0")
        {
            Q[P] = "1";
        }
        else
        {
            I = Array.IndexOf(Q, "0");
            if (I >= 0)
            {
                if (I < P)
                {
                    for (int i = I; i <= P; i++)
                    {
                        Q[i] = (i == P) ? "1" : Q[i + 1];
                    }
                }
                else if (I > P)
                {
                    for (int i = I; i >= P; i--)
                    {
                        Q[i] = (i == P) ? "1" : Q[i - 1];
                    }
                }
            }
        }

        foreach (String s in Q)
            Console.Write(s + " ");
    }

    static void Main()
    {
        String[] X = {"a", "b", "0", "c", "d", "0"};
        placeAt(X , 1);

    }

}

Випробування введіть тут опис зображення


1
це не працює([0, 'a', 'b', 0, 'c', 'd'], 2)
eguneys

1
Ви можете зберегти деякі символи, видаливши всі непотрібні пробіли, наприклад , String[] Q, int Pдо String[]Q,int P.
ProgramFOX

Привіт @eguneys, дякую, що вказав на це. Я змінив логіку і таким чином працює для всіх ваших тестових випадків. Я також оновив образ тестових випадків. Розміщення зроблено правильно, проте результати зсуву відрізняються.
Merin Nakarmi

Привіт @ProgramFOX, дякую за цінний коментар. Я врятував десь 10 символів.
Merin Nakarmi

0

C, 154 байти

p(a,l,i,c)int*a;{for(c=i;c+1;c--){if(!a[c]){for(;c<i;c++)a[c]=a[c+1];return a[i]=1;}}for(c=i;c<l;c++){if(!a[c]){for(;c>i;c--)a[c]=a[c-1];return a[i]=1;}}}

Проходить дані тестові випадки, a - вказівник на масив, l - довжина масиву (я сподіваюся, що це не порушує короткий показник), i - індекс для вставки та c використовується внутрішньо. Можливо, це можна покращити, комбінуючи пошук лівої та правої петель.

Приклад

int main(int argc, char * argv[]) {
    int a[] = {0, 2, 0, 2};
    p(a, 4, 3);
}

Безумовно

Прямо вперед, і насправді не будь-які хитрощі, ніж оголошення декларації стилю K&R

p(a,l,i,c) int *a; {
    /* Search left from i (also handles a[i] == 0) */
    for (c=i;c+1;c--) {
            if (!a[c]) {
                    /* Shift items left until i */ 
                    for (;c<i;c++) a[c]=a[c+1];
                    return a[i]=1;
            }
    }
    /* Search right from i */
    for (c=i;c<l;c++) {
            if(!a[c]) {
                    /* Shift items right until i */
                    for(;c>i;c--) a[c]=a[c-1]; 
                    return a[i]=1;
            }
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.