Remplissez les espaces vides en remplissant les espaces vides


10

Écrivez une fonction (telle que placeAt) qui prend un tableau d'entiers non négatifs et un index qui est un entier non négatif. Il devrait placer un 1 à l'indice donné, décalant éventuellement les autres entrées d'un endroit pour quitter cet endroit, avec 0 pour les espaces vides.

  • Si l'entrée à l'index souhaité est 0, remplissez-la avec un 1.
  • Sinon, recherchez le 0 le plus proche à gauche de l'index. Décalez les entrées d'une place vers la gauche pour faire de la place, puis remplissez l'index avec un 1.
  • S'il n'y a pas de 0 à gauche, faites de même en allant à droite.
  • Si aucun n'est possible (c'est-à-dire s'il n'y a pas de 0), retournez le tableau tel quel.

Les éléments sont indexés 0. Le nom de la fonction peut être tout ce que vous voulez.

Exemples:

(Les lettres représentent toutes les valeurs entières positives.)

[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

Il s'agit d'un défi de golf de code. L'entrée la plus courte au bout de 9 jours l'emporte.


4
Comment savez-vous s'il faut déplacer à gauche ou à droite lorsque les deux sont possibles? Et s'il n'y en a pas 0?
xnor

Car [0, 2, 0, 2] placeAt 3, est-il légal de produire [2, 0, 2, 1]? Le code doit-il être réellement une fonction appelée placeAt? Notez que certaines langues n'ont pas exactement de fonctions. "Lancer une exception" peut également ne pas s'appliquer à certaines langues; Je suggère d'autoriser une sortie indiquant une erreur.
xnor

Le tableau peut-il avoir des valeurs négatives?
Kade

Je suis sûr à 99% que je comprends les intentions du PO avec les règles de ce défi, j'ai donc réorganisé le message (il est dans la file d'attente en ce moment) et je vais essayer de répondre aux questions. eguneys, vous pouvez corriger n'importe laquelle de mes réponses si besoin est.
ETHproductions

@xnor Le décalage vers la gauche a toujours la préférence sur le décalage vers la droite. S'il n'y a pas de 0, renvoyez simplement le tableau d'origine. En outre, ce [2, 0, 2, 1]n'est pas une sortie légale, car vous devez toujours déplacer le moins d'éléments possible et vous pouvez nommer la fonction comme vous le souhaitez.
ETHproductions

Réponses:


4

JavaScript (ES6), 85

Testez l'exécution de l'extrait sur n'importe quel navigateur compatible EcmaScript 6 (notamment pas Chrome ni MSIE. J'ai testé sur Firefox, Safari 9 pourrait aller)

(J'ai trouvé cela sans regarder les autres réponses, maintenant je vois que c'est très similaire à la patinoire. Pourtant, assez court. Probablement, je n'aurai pas beaucoup de votes positifs pour celle-ci)

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 parce que je viens d'apprendre l'existence de l'opérateur virgule et pour m'avoir battu
rink.attendant.6

@ rink.attendant.6 mais votre utilisation de && pour rejoindre le spliceest mieux que ma virgule
edc65

3

Julia, 122 octets

Juste une implémentation naïve de la spécification pour démarrer.

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)

Non 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

1

JavaScript (ES6), 98 octets

À peu près la même approche que ma réponse CoffeeScript, mais je court-circuite à l'extrême afin de sauvegarder une returndéclaration:

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

Explication

Pour l'expliquer plus facilement, j'ai réorganisé un peu mon code:

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

Voici quelques informations sur l'évaluation des courts-circuits JS.

Démo

Pour le moment, cette démo ne fonctionne que dans Firefox et Edge en raison de l'utilisation d'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>


Comment cela fonctionne-t-il?
eguneys

@eguneys Explication ajoutée
rink.attendant.6

cela ne fonctionne pas pourf(['a', 'b', 0, 'c', 'd', 0], 2)
eguneys

@eguneys Fixed. J'ai oublié que CoffeeScript en ajoute automatiquement un lors de l'utilisation de leur raccourci [a..b].
rink.attendant.6

ne fonctionne pas pourf(['a', 'b', 0, 'c', 'd', 0], 1)
eguneys

1

Rubis, 208 octets

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

Bienvenue chez PPCG! Quelques conseils de golf simples pour Ruby: vous n'avez pas besoin de retrait, vous pouvez donc vous débarrasser de tous les espaces. Ensuite, vous n'avez pas non plus besoin des points-virgules, car une seule nouvelle ligne représente le même nombre d'octets. Les appels de méthode à la fin d'une instruction n'ont pas besoin de parenthèses, vous pouvez donc, par exemple .rindex 0, enregistrer un octet à chaque fois. Vous pouvez également enregistrer quelques octets en utilisant un proc au lieu d'une méthode, qui ne dispose même pas d'être nommé: ->a,i{...}. L'if / elsif / elsif peut probablement être raccourci avec un opérateur ternaire imbriqué ...?...:...?...:....
Martin Ender

Merci beaucoup pour ces aimables conseils. Je vais l'examiner et voir ce que je peux faire.
handrake

1

Haskell, 119 octets

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

Exemple d'utilisation:

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

Comment ça marche: Divisez la liste d'entrée à la position donnée en partie gauche a, l'élément à la position elle x- même et la partie droite b. S'il y a un 0in a++x, faites de la place au premier 0dans le sens inverse a++x. S'il y a une 0entrée x++b, faites-y de la place. S'il n'y a pas 0du tout, combinez toutes les parties inchangées pour obtenir à nouveau la liste d'origine.


0

CoffeeScript, 96 octets

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 octets

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

Calcule l'index du zéro à supprimer en concaténant la liste inversée jusqu'à l'index d'insertion avec la partie après l'index dans l'ordre normal, puis en trouvant l'indice du premier zéro. Un zéro est ajouté à la fin pour éviter les ValueErrorexceptions quand aucun zéro n'est trouvé. Ensuite, supprimez, insérez et revenez.


0

R, 87 octets

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

Explication

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

Les tests

> 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 octets

Golfé (265 caractères)

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

Avec des espaces blancs et des empreintes

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

Programme complet

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

    }

}

Cas de test entrez la description de l'image ici


1
cela ne fonctionne pas pour([0, 'a', 'b', 0, 'c', 'd'], 2)
eguneys

1
Vous pouvez enregistrer certains caractères en supprimant tous les espaces inutiles, par exemple String[] Q, int Ppour String[]Q,int P.
ProgramFOX

Salut @eguneys, merci de l'avoir signalé. J'ai modifié la logique et fonctionne donc pour tous vos cas de test. J'ai également mis à jour l'image des cas de test. Le placement est effectué correctement, mais les résultats de décalage sont différents.
Merin Nakarmi

Salut @ProgramFOX, merci pour votre précieux commentaire. J'ai enregistré une dizaine de caractères.
Merin Nakarmi

0

C, 154 octets

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

Passe les cas de test donnés, a est le pointeur vers le tableau, l est la longueur du tableau (j'espère que cela ne rompt pas le brief), i est l'index de l'insert et c est utilisé en interne. Pourrait éventuellement être amélioré en combinant la recherche gauche et droite des boucles.

Exemple

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

Non golfé

Simple, et pas vraiment d'astuces au-delà de la déclaration de style 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;
            }
    }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.