위치 별 욕실 에티켓


24

배경

화장실 에티켓은 이용 가능한 소변기에 관한 다음 채워진 소변기가 전체 불편 함을 최소화하는 것이어야한다고 말합니다. 총 불편도 방정식은 다음 방정식 세트로 제공됩니다.

dist (x, y) = 소변기 단위에서 사람 x와 사람 y 사이의 선형 거리
 불편 함 (x) = 합 x를 제외한 모든 사람 y에 대한 합 (1 / (dist (x, y) * dist (x, y)))
 total_Discomfort = 모든 x에 대한 합 (불편 (x))

비슷한 (정확히 동일하지는 않음) 문제를 다루는 더 심층적 인 종이는 여기에서 찾을 수 있습니다 .


입출력

빈 소변기 및 완전 소변기의 입력이 주어지면 한 사람을 추가하여 결과 소변기 세트를 출력하십시오. 위치에 넥타이가있는 경우 소변기는 왼쪽에서 오른쪽으로 채워야합니다. 출력은 입력과 동일한 형식이어야합니다.

  • 소변이 가득 찬 경우 입력을 반환하십시오.
  • 입력은 항상 하나 이상의 소변기가 정의됩니다.


테스트 사례

입력-> 출력
1000001-> 1001001
101010101-> 111010101
100-> 101
00000-> 10000
1111111-> 1111111
0100-> 0101
101000-> 101001


규칙

이것은 이므로 바이트 단위의 가장 짧은 코드가 이깁니다. 표준 루프 홀은 금지되어 있습니다.



1
답변을 수락하기 전에 일주일 정도 기다리는 것이 좋습니다. 하루 이내에 수락하면 도전에 대한 답변 수가 줄어들 수 있습니다.
Emigna

1
나는 테스트 케이스를 추가 0100하고 101000테스트 할 것을 제안한다 (일부 정규식 기반 접근법은 실제 테스트 케이스에서 작동하지만 여전히 처리 해야하는 경우에는 작동하지 않을 것이다)
Dada


@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

자바 스크립트 (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))

그리고 우리는 최적의 소변기 지수를 가지고 있습니다. 우리는이 인덱스에 값을 대체 x1. 입력의 경우 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

그 공백 팁에 감사드립니다. 나는 확실히 몰랐다. 대단해!
bioweasel 오전

그 공백 팁은 Python 2에서만 작동한다고 생각합니다. 아마도 Python 3의 초기 버전이지만 idk 일 수 있습니다. Python 2 또는 특정 버전의 3으로 답변을 제한해야합니다.
mbomb007

유휴 상태의 3.5.2 셸에서 실행 중이며 문제없이 실행
중이므로

2

파이썬 3 574 471 347 바이트

다른 파이썬 솔루션이이 솔루션의 5 분의 1과 같다는 점을 고려해 보면 아마 이것에 대해 좀 더 노력할 것입니다.

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.