Llenar espacios vacíos llenando espacios vacíos

10

Escriba una función (como placeAt) que tome una matriz de enteros no negativos y un índice que sea un entero no negativo. Debería colocar un 1 en el índice dado, posiblemente desplazando otras entradas por un lugar para desocupar ese lugar, con 0 para espacios vacíos.

  • Si la entrada en el índice deseado es 0, llénela con un 1.
  • De lo contrario, busque el 0 más cercano a la izquierda del índice. Desplaza las entradas un lugar a la izquierda en ese 0 para hacer espacio, luego llena el índice con un 1.
  • Si no hay 0 a la izquierda, haz lo mismo yendo a la derecha.
  • Si ninguno de los dos es posible (es decir, si no hay 0), devuelva la matriz sin cambios.

Los artículos están indexados a 0. El nombre de la función puede ser lo que quieras.

Ejemplos:

(Las letras representan cualquier valor entero positivo).

[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

Este es un desafío de código de golf. La entrada más corta al final de 9 días gana.

eguneys
fuente
44
¿Cómo sabe si debe desplazarse hacia la izquierda o hacia la derecha cuando ambos son posibles? Además, ¿qué pasa si no hay 0?
xnor
Porque [0, 2, 0, 2] placeAt 3, ¿es legal la salida [2, 0, 2, 1]? ¿Se requiere que el código sea realmente una función llamada placeAt? Tenga en cuenta que algunos idiomas no tienen exactamente funciones. "Lanzar una excepción" también podría no aplicarse a algunos idiomas; Sugeriría permitir una salida que indique un error.
xnor
¿Puede la matriz tener valores negativos?
Kade
Estoy 99% seguro de que entiendo las intenciones del OP con las reglas de este desafío, por lo que he reorganizado la publicación (está en la cola en este momento) e intentaré responder preguntas. Eguneys, puede corregir cualquiera de mis respuestas si es necesario.
ETHproductions
@xnor El desplazamiento a la izquierda siempre tiene preferencia sobre el desplazamiento a la derecha. Si no hay 0, simplemente devuelva la matriz original. Además, [2, 0, 2, 1]no es una salida legal, ya que siempre debe cambiar la menor cantidad de elementos posible, y puede nombrar la función como desee.
ETHproductions

Respuestas:

4

JavaScript (ES6), 85

Pruebe a ejecutar el fragmento en cualquier navegador compatible con EcmaScript 6 (en particular, no Chrome ni MSIE. Probé en Firefox, Safari 9 podría funcionar)

(Encontré esto sin mirar ninguna de las otras respuestas, ahora veo que es muy similar a la pista. Sin embargo, bastante más corto. Probablemente no obtendré muchos votos a favor para esta)

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>

edc65
fuente
+1 porque acabo de enterarme del operador de coma y de golpearme
rink.attendant.6
@ rink.attendant.6 pero su uso de && para unirse splicees mejor que mi coma
edc65
3

Julia, 122 bytes

Solo una implementación ingenua de la especificación para comenzar las cosas.

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)

Sin golf:

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
Alex A.
fuente
1

JavaScript (ES6), 98 bytes

Prácticamente el mismo enfoque que mi respuesta de CoffeeScript, pero estoy haciendo un corto circuito al extremo para guardar una returndeclaración:

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

Explicación

Para explicarlo más fácilmente, he reorganizado un poco mi código:

// 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
}

Aquí hay información sobre la evaluación de cortocircuito de JS.

Manifestación

Por el momento, esta demostración solo funciona en Firefox y Edge debido al uso de 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>

rink.attendant.6
fuente
¿Cómo funciona? ¿Puedes explicarlo por favor?
eguneys
@eguneys Explicación agregada
rink.attendant.6
no funciona paraf(['a', 'b', 0, 'c', 'd', 0], 2)
eguneys
@eguneys fijo. Olvidé que CoffeeScript agrega automáticamente uno al usar su corte abreviado [a..b].
rink.attendant.6
no funciona paraf(['a', 'b', 0, 'c', 'd', 0], 1)
eguneys
1

Rubí, 208 bytes

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
rastrillo de mano
fuente
Bienvenido a PPCG! Algunos consejos de golf simples para Ruby: no necesita ninguna sangría, por lo que puede deshacerse de todos los espacios. Entonces tampoco necesita los puntos y comas, porque una nueva línea es el mismo número de bytes. Las llamadas al método al final de una declaración no necesitan paréntesis, por lo que puede hacerlo, por ejemplo .rindex 0, guardar un byte cada vez. También se puede ahorrar algo de bytes mediante el uso de un proc en lugar de un método, que ni siquiera tienen nombre: ->a,i{...}. El if / elsif / elsif probablemente se puede acortar con un operador ternario anidado ...?...:...?...:....
Martin Ender
Muchas gracias por el amable consejo. Lo investigaré y veré qué puedo hacer.
handrake
1

Haskell, 119 bytes

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

Ejemplo de uso:

*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]

Cómo funciona: Divida la lista de entrada en la posición dada en la parte izquierda a, el elemento en la posición misma xy la parte derecha b. Si hay un 0en a++x habitación, completar al primero 0en el reverso de a++x. Si hay una 0en x++b, sala de maquillaje allí. Si no hay ninguno 0, combine todas las partes sin cambios para obtener la lista original nuevamente.

nimi
fuente
0

CoffeeScript, 96 bytes

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

Python 2, 102 bytes

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

Calcula el índice del cero que se eliminará concatenando la lista invertida hasta el índice de inserción con la parte después del índice en orden normal, y luego encuentra el índice del primer cero. Se agrega un cero al final para evitar ValueErrorexcepciones cuando no se encuentra ningún cero. Luego simplemente borre, inserte y regrese.

samgak
fuente
0

R, 87 bytes

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

Explicación

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

Pruebas

> 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
> 
MickyT
fuente
0

C #, 265 bytes

Golfizado (265 Personajes)

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+" ");}

Con espacios en blanco y hendiduras

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 + " ");
    }

Programa completo

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);

    }

}

Casos de prueba ingrese la descripción de la imagen aquí

Merin Nakarmi
fuente
1
esto no funciona para([0, 'a', 'b', 0, 'c', 'd'], 2)
eguneys
1
Puede guardar algunos caracteres eliminando todos los espacios en blanco innecesarios, por ejemplo, String[] Q, int Pa String[]Q,int P.
ProgramFOX
Hola @eguneys, gracias por señalarlo. He modificado la lógica y, por lo tanto, funciona para todos sus casos de prueba. También he actualizado la imagen de los casos de prueba. La colocación se realiza correctamente, sin embargo, los resultados de los cambios son diferentes.
Merin Nakarmi
Hola @ProgramFOX, gracias por tu valioso comentario. Salvé unos 10 caracteres.
Merin Nakarmi
0

C, 154 bytes

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;}}}

Pasa los casos de prueba dados, a es el puntero a la matriz, l es la longitud de la matriz (espero que esto no rompa el resumen), i es el índice para la inserción y yc se usa internamente. Posiblemente podría mejorarse combinando la búsqueda izquierda y derecha de bucles.

Ejemplo

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

Sin golf

Directo, y realmente no hay ningún truco más allá de la declaración de estilo 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;
            }
    }
}
David Wotherspoon
fuente