Позиційний етикет для ванної


24

Фон

Етикет у ванній кімнаті, коли йдеться про доступні пісуари, говорить, що наступне письмове письмове приміщення повинно бути таким, яке мінімізує повний дискомфорт. Повне рівняння дискомфорту задається наступним набором рівнянь:

dist (x, y) = лінійна відстань між людиною x та людиною y в сечових блоках
 дискомфорт (x) = сума (1 / (dist (x, y) * dist (x, y))) для всіх осіб y без урахування особи x
 total_Discomfort = сума (дискомфорт (x)) для всіх x

Більш глибокий документ, що стосується подібної (не зовсім тієї самої) проблеми, можна знайти тут: (Дякую @Lembik за те, що він попередив мене про цю дивовижну газету!)


Введення-виведення

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

  • Якщо вам надано справу з повним письмером, поверніть дані.
  • Вхід завжди матиме принаймні один пісуар.


Випробування

ВХОД -> ВИХІД
1000001 -> 1001001
101010101 -> 111010101
100 -> 101
00000 -> 10000
1111111 -> 1111111
0100 -> 0101
101000 -> 101001


Правила

Це , тому найкоротший код у байтах виграє. Стандартні петлі-отвори заборонені.



1
Рекомендується почекати близько тижня, перш ніж приймати відповідь. Прийняття менше ніж за день може зменшити кількість відповідей на ваш виклик.
Емінья

1
Я б запропонував додати 0100і 101000в тестові випадки (деякі підходи, засновані на регулярних виразках, працюють над фактичними тестовими кейсами, але не працюватимуть на тих, з якими все-таки слід обробляти)
Dada

також пов’язано: codegolf.stackexchange.com/questions/94074/…
Тит

@TheBitByte Як це образливо? Це досить точний опис того, як чоловіки вибирають пісуари у ванній кімнаті.
mbomb007

Відповіді:


3

Желе , 13 12 байт

J_þTݲSiṂ$Ṭo

Спробуйте в Інтернеті! або Перевірте всі тестові випадки.

Пояснення

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

10

MATL , 19 18 17 байт

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

Спробуйте в Інтернеті! Або перевірити всі тестові випадки (трохи змінений код).

Пояснення

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

Візьмемо [1 0 0 0 0 0 1]приклад як приклад.

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

4

JavaScript (ES6), 89 байт

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

Виводиться шляхом зміни вхідного масиву.


4

R, 83 76 67 байт

Щойно зрозумів, що я можу зберегти декілька байтів, не намагаючись перевірити, чи не пустують кандидатські пісуари. Непорожні пісуари завжди будуть повертати Infзначення дискомфорту, тому вони виключаються в процесі розрахунку. Крім того, просто використовуйте пряме індексування, а не replaceкоротше, але менш елегантно.

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

Пояснення

x=scan()

Ми читаємо поточний стан з stdin і називаємо його x. Ми вважаємо, що вхід - це послідовність 1s і 0s, розділених пробілами чи новими рядками. Скажімо, для цілей пояснення ми вводимо інформацію1 0 0 0 0 0 1 .

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

Заміняємо значення x у конкретному індексі на 1. Все, що знаходиться між, - [ ]це з'ясування того, що найкращий індекс.

Оскільки існуючі пісуари незмінні, нам не потрібно враховувати відстані між ними. Потрібно лише врахувати відстані між зайнятими пісорами та можливим новим. Тож ми визначаємо показники зайнятих пісуарів. Ми використовуємо whichфункцію для повернення індексів логічного вектора, які є TRUE. Усі числа в R, примушені до типу logical, є TRUEненульовими та FALSEнульовими. Просто це which(x)призведе до помилки типу argument to 'which' is not logical, як xі числовий вектор. Тому ми повинні примусити це до логічного. !є логічною функцією заперечення R, яка автоматично примушує до логічного. Застосовуючи його двічі, !!xвиходить вектор TRUEіFALSEіз зазначенням того, які пісуари зайняті. (Альтернативні байти-еквівалентні Приведення до логічного включати логічні оператори &і |і вбудовані команди Tі F, наприклад , F|xабоT&xі так далі. !!xвиглядає більш вигукувально, тому ми використаємо це.)

                                 which(!!x)

Це поєднується з тим seq(x), що повертає цілу послідовність від 1довжини x, тобто всіх місць сечовипускання (і, таким чином, усі можливі місця, які слід врахувати).

                          seq(x)

Тепер у нас є індекси наших зайнятих пісуарів: 1 7і наших порожніх пісуарів 1 2 3 4 5 6 7. Переходимо `-`, функцію віднімання, доouter функції, щоб отримати "зовнішнє віднімання", яка є наступною матрицею відстаней між усіма пісуарами та зайнятими пісуарами:

[, 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),`-`)

Ми піднімаємо це до -2сили. (Для тих, хто трохи загубився, в ОП «дискомфорт» визначається як 1 / (distance(x, y) * distance(x, y)), що спрощує до 1/d(x,y)^2, тобто d(x,y)^-2)

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

Візьміть суму кожного рядка в матриці.

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

Отримайте індекс найменшого значення, тобто оптимальний пісуар. У випадку декількох найменших значень повертається перше (тобто крайнє ліве).

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

І вуаля, у нас є індекс оптимального пісору. Заміняємо значення цього індексу на xна 1. Що стосується 1111введення, не має значення, який ми замінимо, у нас все одно буде дійсний вихід.

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

Повернути змінений вхід.

x

2

PHP, 135 байт

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

Я впевнений, що це значно швидше це зробити, але у мене нечітка голова і не можу придумати її!

Старий код

Код без мінімізації:

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

2

Пітон 3 223 222 165 байт

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

Крикніть mbomb007, щоб отримати поради щодо білого простору та компараторів. Також я побачив, що мій онлайн-лічильник знімав усі вкладки та перетворював їх у пробіли, тому кількість рахунків набагато менша, ніж у мене було спочатку

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

Показано переглянутий пробіл:

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

Оригінал:

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

Це очікує, що рядок, переданий йому як 1, так і 0, "10001"повертає рядок"10101"

Редагувати: Змінено 1/float((j-i)**2)наfloat((j-i)**-2)


!='1'може бути <'1'і =='1'може бути >'0'. Також врахуйте цю пораду
mbomb007

Дякуємо за підказку пробілу. Я точно цього не знав. Це круто!
біовезелок

Ця думка пробілу працює лише в Python 2, я думаю. Можливо рання версія Python 3, але idk. Вам доведеться обмежити свою відповідь Python 2 або деякою конкретною версією 3, коли вона працює.
mbomb007

У мене він працює в оболонці 3.5.2 в IDLE, і він працює без проблем, тому я думаю, що все-таки все добре
bioweasel

2

Python 3, 574 471 347 байт

Я, мабуть, ще над цим попрацюю, враховуючи, що інше рішення Python - це як п'ята частина цього: [.

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)

Ну це набагато краще зараз, коли я дізнався, що ви можете використовувати одинарні пробіли.


1

Пітон, 165 163 158 147 141 140 139 байт

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

перепишіть другий рядок, if"1"*len(p)==p:return pщоб зберегти байт
FlipTack
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.