Étiquette de salle de bain positionnelle

24

Contexte

L'étiquette de la salle de bain, en ce qui concerne les urinoirs disponibles, indique que le prochain urinoir à remplir doit être celui qui minimise l'inconfort total. L'équation de l'inconfort total est donnée par l'ensemble d'équations suivant:

dist (x, y) = distance linéaire entre la personne x et la personne y dans l' inconfort des unités d'urinoir
 (x) = somme (1 / (dist (x, y) * dist (x, y))) pour toutes les personnes y à l'exclusion de la personne x
 total_Discomfort = somme (inconfort (x)) pour tous les x

Un article plus approfondi traitant d'un problème similaire (pas exactement le même) peut être trouvé ici: (Merci à @Lembik de m'avoir alerté de ce livre blanc étonnant!)


Entrée sortie

Étant donné l'entrée d'urinoirs vides et pleins, sortez l'ensemble d'urinoirs résultant avec l'ajout d'une personne. S'il y a une égalité pour une position, les urinoirs doivent se remplir de gauche à droite. La sortie doit être au même format que l'entrée.

  • Si on vous donne un cas avec des urinoirs pleins, renvoyez l'entrée.
  • L'entrée aura toujours au moins un urinoir défini.


Cas de test

ENTRÉE -> SORTIE
1000001 -> 1001001
101010101 -> 111010101
100 -> 101
00000 -> 10000
1111111 -> 1111111
0100 -> 0101
101000 -> 101001


Règles

C'est le , donc le code le plus court en octets gagne. Les trous de boucle standard sont interdits.

Nick Frev
la source
1
Il est recommandé d'attendre environ une semaine avant d'accepter une réponse. Accepter en moins d'une journée peut réduire le nombre de réponses reçues par votre défi.
Emigna
1
Je suggérerais d'ajouter 0100et 101000dans les cas de test (une approche basée sur des expressions rationnelles fonctionne sur les cas de test réels mais ne fonctionnera pas sur ceux qui devraient encore être traités)
Dada
@TheBitByte Comment est-ce offensant? C'est une description assez précise de la façon dont les hommes choisissent les urinoirs dans une salle de bain.
mbomb007

Réponses:

3

Gelée , 13 12 octets

J_þTݲSiṂ$Ṭo

Essayez-le en ligne! ou Vérifiez tous les cas de test.

Explication

J_þTݲSiṂ$Ṭo  Input: boolean array A
J             Indices, returns [1, 2, ..., len(A)]
   T          Truthy indices, returns the indices which have a truthy value
 _þ           Form the subtraction (_) table (þ) between them
    İ         Inverse, find the reciprocal of each
     ²        Square each
      S       Sum the sublists column-wise
         $    Monadic chain
        Ṃ       Minimum
       i        Find the first index of that
          Ṭ   Untruth indices, returns a boolean array with 1's at those indices
           o  Logical OR between that and A, and return
miles
la source
10

MATL , 19 18 17 octets

lyf!Gn:-H_^Xs&X<(

Essayez-le en ligne! Ou vérifiez tous les cas de test (code légèrement modifié).

Explication

Il suffit de calculer la distance de chaque nouvelle position potentielle à celles déjà occupées. Les distances restantes ne dépendent pas de la nouvelle position potentielle et constituent donc un terme constant, qui peut être ignoré.

Prenons l' [1 0 0 0 0 0 1]exemple de la saisie .

l      % Push 1
       % STACK: 1
y      % Take input implicitly. Duplicate from below
       % STACK: [1 0 0 0 0 0 1], 1, [1 0 0 0 0 0 1]
f!     % Indices of nonzero elements, as a column array
       % STACK: [1 0 0 0 0 0 1], 1, [1 7]
Gn:    % Push [1 2 ... n], where n is input size (array of possible positions)
       % STACK: [1 0 0 0 0 0 1], 1, [1; 7], [1 2 3 4 5 6 7]
-      % Matrix with all pairs of differences 
       % STACK: [1 0 0 0 0 0 1], 1, [1; 7], [0 -1 -2 -3 -4 -5 -6;
                                             6  5  4  3  2  1  0]
H_^    % Raise each entry to -2
       % STACK: [1 0 0 0 0 0 1], 1, [   Inf 1.0000 0.2500 0.1111 0.0625 0.0400 0.0278;
                                     0.0278 0.0400 0.0625 0.1111 0.2500 1.0000    Inf]
Xs     % Sum of each column
       % STACK: [1 0 0 0 0 0 1], 1, [Inf 1.04 0.3125 0.2222 0.3125 1.04 Inf]
&X<    % Index of minimum. Takes the first if there is a tie
       % STACK: [1 0 0 0 0 0 1], 1, 4
(      % Assign: write 1 at the position of the minimizer
       % STACK: [1 0 0 1 0 0 1]
       % Implicitly display
Luis Mendo
la source
4

JavaScript (ES6), 89 octets

a=>a[a.map((e,i)=>!e&&(t=0,a.map((e,j)=>t+=(j-=i)&&e/j/j),t<m&&(m=t,k=i)),k=0,m=1/0),k]=1

Sorties en modifiant le tableau d'entrée.

Neil
la source
4

R, 83 76 67 octets

Je viens de réaliser que je peux économiser plusieurs octets en ne prenant pas la peine de vérifier si les urinoirs candidats sont vides. Les urinoirs non vides renverront toujours une Infvaleur d'inconfort, ils sont donc exclus au cours du calcul. En outre, il suffit d'utiliser l'indexation directe plutôt que replace, donc c'est plus court mais moins élégant.

x=scan()
x[which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))]=1
x

Explication

x=scan()

Nous lisons l'état actuel de stdin et l'appelons x. Nous supposons que l'entrée est une séquence de 1s et 0s séparés par des espaces ou des retours à la ligne. Aux fins de l'explication, disons que nous saisissons 1 0 0 0 0 0 1.

x[which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))]=1

Nous remplaçons une valeur de xà un indice particulier par 1. Tout entre le[ ] détermine quel est le meilleur index.

Étant donné que les urinoirs existants sont immuables, nous n'avons pas besoin de considérer les distances entre eux. Il suffit de considérer les distances entre les urinoirs occupés et le nouveau éventuel. Nous déterminons donc les indices des urinoirs occupés. Nous utilisons whichune fonction pour renvoyer les indices d'un vecteur logique qui le sont TRUE. Tous les nombres de R, lorsqu'ils sont contraints de taper logical, sont TRUEsi différents de zéro et FALSEs'ils sont nuls. Faire simplement which(x)entraînera une erreur de type argument to 'which' is not logical, tout comme xun vecteur numérique. Nous devons donc le contraindre à la logique. !est la fonction de négation logique de R, qui contraint automatiquement à logique. En l'appliquant deux fois !!x,, donne un vecteur de TRUEetFALSE indiquant quels urinoirs sont occupés. (Les coercitions équivalentes en octets alternatives à la logique impliquent les opérateurs logiques& et |et les commandes internes Tet F, par exemple F|xou T&xet ainsi de suite. !!xSemble plus exclamatif, nous allons donc l'utiliser.)

                                 which(!!x)

Ceci est associé à seq(x), qui renvoie la séquence entière de 1à la longueur de x, c'est-à-dire tous les emplacements d'urinoirs (et donc tous les emplacements possibles à considérer).

                          seq(x)

Nous avons maintenant les indices de nos urinoirs occupés: 1 7et de nos urinoirs vides 1 2 3 4 5 6 7. On passe `-`, la fonction de soustraction, à la outerfonction pour obtenir la "soustraction externe", qui est la matrice de distances suivante entre tous les urinoirs et les urinoirs occupés:

[, 1] [, 2]

[1,] 0 -6

[2,] 1 -5

[3,] 2 -4

[4,] 3 -3

[5,] 4 -2

[6,] 5 -1

[7,] 6 0

                    outer(seq(x),which(!!x),`-`)

Nous élevons cela à la -2puissance e. (Pour ceux qui sont un peu perdus, au PO, le "malaise" est défini comme 1 / (distance(x, y) * distance(x, y)), ce qui simplifie 1/d(x,y)^2, c'est- à -dire d(x,y)^-2.)

                    outer(seq(x),which(!!x),`-`)^-2

Prenez la somme de chaque ligne de la matrice.

            rowSums(outer(seq(x),which(!!x),`-`)^-2)

Obtenez l'indice de la plus petite valeur, c'est-à-dire l'urinoir optimal. Dans le cas de plusieurs plus petites valeurs, la première (c'est-à-dire la plus à gauche) est renvoyée.

  which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))

Et voilà, nous avons l'indice de l'urinoir optimal. Nous remplaçons la valeur de cet indice xpar 1. Dans le cas d'une 1111entrée, peu importe celle que nous remplaçons, nous aurons toujours une sortie valide.

x[which.min(rowSums(outer(seq(x),which(!!x),`-`)^-2))]=1

Renvoie l'entrée modifiée.

x
rturnbull
la source
2

PHP, 135 octets

$a=explode(1,$argv[1]);$b=0;foreach($a as$c=>$d){$l=strlen($d);if($l>$b){$b=$l;$e=$c;}}if($b)$a[$e][intval($b/2)]=1;echo implode(1,$a);

Je suis sûr qu'il y a une façon beaucoup plus rapide de le faire, mais j'ai la tête floue et je ne peux pas y penser!

Ancien code

Le code sans minification:

$a=explode(1,$argv[1]);
$b=0;
foreach($a as $c=>$d){
    $l=strlen($d);
    if($l>$b){
        $b=$l;
        $e=$c;
    }
}
if($b){
    $a[$e][intval($b/2)]=1;
}
echo implode(1,$a);
CT14.IT
la source
2

Python 3 223 222 165 Octets

D'accord, je sais que ce n'est pas la plus jolie réponse là-bas, et je suis sûr que cela peut être joué un peu, mais je ne faisais que déconner et voir ce que je pouvais faire

Criez à mbomb007 pour obtenir des conseils sur les espaces et les comparateurs. De plus, j'ai vu que mon compteur de personnages en ligne prenait tous les onglets et les transformait en espaces, donc le nombre est beaucoup moins élevé que ce que j'avais à l'origine

def u(a):
 m,r,x=9,0,len(a)
 for i in range(x): 
    d=0
    if a[i]<'1':
     for j in range(x):
        if a[j]>'0':d+=float((j-i)**-2)
     if d<m:r=i;m=d
 return a[:r]+'1'+a[r+1:]

Affichage de l'espace blanc révisé:

def u(a):
<sp> m,r,x=9,0,len(a)
<sp> for i in range(x): 
<tab> d=0
<tab> if a[i]<'1':
<tab><sp> for j in range(x):
<tab><tab> if a[j]>'0':d+=float((j-i)**-2)
<tab><sp> if d<m:r=i;m=d
<sp> return a[:r]+'1'+a[r+1:]

Original:

def u(a):
    m,r,x=9,0,len(a)
    for i in range(x): 
        d=0
        if a[i]!='1':
            for j in range(x):
                if a[j]=='1':d+=float(1/(j-i)**2)
            if d<m:r=i;m=d
    return a[:r]+'1'+a[r+1:]

Cela attend une chaîne qui lui est passée de 1 et 0 comme "10001"et retourne une chaîne"10101"

Modifier: changé 1/float((j-i)**2)enfloat((j-i)**-2)

belette
la source
!='1'peut être <'1'et =='1'peut être >'0'. En outre, considérez cette astuce
mbomb007
Merci pour cette astuce. Je ne savais absolument pas ceci. C'est génial!
bioweasel
Cette astuce espace ne fonctionne que dans Python 2, je pense. Peut-être la première version de Python 3, mais idk. Vous devrez restreindre votre réponse à Python 2 ou à une version spécifique de 3 pour que cela fonctionne.
mbomb007
Je l'ai en cours d'exécution dans un shell 3.5.2 dans IDLE et il fonctionne sans problème, donc je pense que ça va toujours
bioweasel
2

Python 3, 574 471 347 octets

Je vais probablement y travailler un peu plus, étant donné que l'autre solution Python est comme un cinquième de celle-ci: [.

def a(I):
 D,l,r={},len(I),range
 for i in r(l):
  if I[i]<1:
   n,t,n[i]=I[:],[],1
   for j in r(l):
    if n[j]>0:
     q,Q=[],0
     for k in r(l):
      if k!=j and n[k]>0:q.append((k-j,j-k)[k<j])
     for i in q:Q+=1/(i**2)
    t.append(Q)
   T=sum(t)
   if T not in D.keys():D[T]=i
 if len(D)>0:I[D[min(D.keys())]]=1
 print(I)

Eh bien, c'est beaucoup mieux maintenant que j'ai appris que vous pouvez utiliser des espaces simples.

Yodle
la source
1

Python, 165 163 158 147 141 140 139 octets

def u(p):e=enumerate;a=[(sum((i-j)**-2for j,y in e(p)if"0"<y),i)for i,x in e(p)if"1">x];return a and p[:min(a)[1]]+"1"+p[min(a)[1]+1:] or p
Francisco Couzo
la source
réécrire la deuxième ligne if"1"*len(p)==p:return ppour enregistrer un octet
FlipTack