通过填充空白填充空白


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

数组可以有负值吗?
卡德,2015年

我99%的人确定我了解OP的挑战意图的意图,所以我已经重新整理了帖子(目前正在排队),我将尝试回答问题。eguneys,如果需要,您可以更正我的任何答案。
ETHproductions

@xnor左移始终优先于右移。如果没有0,则只返回原始数组。同样,[2, 0, 2, 1]这也不是合法的输出,因为您应该始终移动尽可能少的元素,并且可以根据需要命名函数。
ETHproductions

Answers:


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.15年

@ rink.attendant.6,但是您使用&&来加入该splice
字母

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短路评估的一些信息

演示版

目前,由于使用了ES6,此演示仅在Firefox和Edge中有效:

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.15年

它不适用于f(['a', 'b', 0, 'c', 'd', 0], 2)
eguneys

@eguneys已修复。我忘了CoffeeScript在使用速记切片时会自动添加一个[a..b]
rink.attendant.15年

不适用于f(['a', 'b', 0, 'c', 'd', 0], 1)
eguneys,2015年

1

Ruby,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!Ruby的一些简单高尔夫技巧:您不需要任何缩进,因此可以消除所有空间。然后,您也不需要分号,因为单个换行符的字节数相同。语句末尾的方法调用不需要括号,因此您可以这样做,例如.rindex 0,每次节省一个字节。您还可以通过使用proc而不是方法来节省一些字节,该方法甚至不必命名为:->a,i{...}。可以使用嵌套三元运算符将if / elsif / elsif缩短...?...:...?...:...
马丁·恩德

非常感谢您的友好建议。我会调查一下,看看能做什么。
handrake

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。如果有0in a++x,则0在的反方向先腾出空间a++x。如果有0in 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 Pto String[]Q,int P
ProgramFOX

嗨@eguneys,谢谢你指出这一点。我已经修改了逻辑,因此适用于所有测试用例。我还更新了测试用例图像。放置正确,但是移位结果不同。
Merin Nakarmi 2015年

嗨,@ ProgramFOX,谢谢您的宝贵评论。我保存了大约10个字符。
Merin Nakarmi 2015年

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;
            }
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.