Позиционный Ванные Этикет

24

Задний план

В этикете ванной комнаты, касающемся имеющихся писсуаров, указывается, что следующий писсуар, который необходимо заполнить, должен быть таким, который сводит к минимуму общий дискомфорт. Общее уравнение дискомфорта задается следующей системой уравнений:

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

Более подробный документ, посвященный аналогичной (не точно такой же) проблеме, можно найти здесь: (Спасибо @Lembik за то, что предупредили меня об этом удивительном техническом описании!)


Ввод, вывод

Учитывая ввод пустых и полных писсуаров, выведите итоговый набор писсуаров с добавлением одного человека. Если есть галстук для позиции, писсуары должны заполнять слева направо. Вывод должен быть в том же формате, что и ввод.

  • Если дан случай с полными писсуарами, верните ввод.
  • На входе всегда будет определен хотя бы один писсуар.


Тестовые случаи

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


правила

Это , поэтому выигрывает самый короткий код в байтах. Стандартные лазейки запрещены.

Ник Фрев
источник
2
Связанная проблема: codegolf.stackexchange.com/questions/47952/the-urinal-protocol
Хоббс
1
Рекомендуется подождать около недели, прежде чем принять ответ. Принятие менее чем за день может уменьшить количество ответов, которые получает ваш вызов.
Emigna
1
Я бы предложил добавить 0100и 101000в тестовых случаях (некоторые основанные на регулярных выражениях подходы работают на реальных тестовых случаях, но не будут работать на тех, которые все еще должны быть обработаны)
Дада
также связанные: 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()

Мы читаем текущее состояние из стандартного ввода и называем его 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
rturnbull
источник
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);
CT14.IT
источник
2

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

bioweasel
источник
!='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)

Ну, теперь гораздо лучше, когда я узнал, что вы можете использовать одиночные пробелы.

Yodle
источник
1

Python, 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