두 벡터의 선형 조합


11

행정상 개요

두 벡터와 각각의 "가중"을 나타내는 입력이 주어지면 해당 벡터의 가중 합도 나타내는 출력을 생성합니다.

도전

입력은 다음 문자 중 하나 이상의 행으로 구성됩니다.

  • 2 차원 평면에서 원점을 나타내는 숫자 0이 정확히 한 번 발생합니다.
  • 정확히 두 개의 다른 숫자 (1-9; 같은 숫자 일 수도 있고 같지 않을 수도 있음), 원점에 대한 위치가 벡터를 나타내고 값이이 벡터에 부착 된 가중치를 나타냄;
  • 일부 "배경 문자". 솔버는 특정 배경 문자를 선택할 수 있습니다. 예를 들어 "."를 선택하겠습니다. (주로 인간의 가독성을 위해). 또는 배경 문자는 공백처럼 보일 수 있습니다.

(솔버는 입력이 단일 다중 행 문자열인지 또는 단일 행 문자열 배열인지 선택할 수 있습니다.)

예를 들어, 입력

....2
.0...
...3.

는 가중치가 2 인 좌표 (3,1)의 벡터와 가중치가 3 인 좌표 (2, -1)의 벡터를 나타냅니다.

출력은 다음과 같이 변경되어 입력과 거의 동일해야합니다.

  • 솔버에 의해 선택된 "결과 문자", 입력 벡터의 가중 합에 의해 지정된 위치 (즉, 입력 벡터의 적절한 선형 조합 인 위치에 추가됨);
  • 동일한 그림에서 원점, 두 개의 입력 벡터 및 출력 벡터를 맞추는 데 필요한 배경 문자 수 원하는 경우 추가 배경 문자를 포함 할 수 있습니다. 유일한 제약은 배경 문자가 보이는 문자이면 전체 출력은 직사각형이어야하고 벡터를 나타내지 않는 모든 문자는 배경 문자 여야한다는 것입니다. 공백이 배경 문자로 사용되는 경우 이러한 제약 조건을 적용하지 않아도됩니다.

(일반적으로 가중치 a를 가진 하나의 벡터 (v, w)와 가중치 b를 가진 두 번째 벡터 (x, y)가 있으면 가중치 합은 a (v, w) + b (x, y) = (av + bx, aw + by).)

이전 예에서 적절한 선형 조합은 2 * (3,1) + 3 * (2, -1) = (12, -1)입니다. 결과 문자로 "X"를 사용하면 출력은 다음과 같습니다.

....2.........
.0............
...3.........X

또는

................
...2............
0...............
..3.........X...
................
................

일반적인 스코어링 : 가장 짧은 대답 (바이트)이 이깁니다.

입력 및 출력 예

공백이 사용되면 위의 입력은 다음과 같습니다.

    2
 0
   3

출력은 다음과 같습니다

    2
 0
   3         X

선행 / 후행 공백 문자 / 줄은 관련이 없습니다. 독자에게 보이지 않으면 괜찮습니다. (즉, 나머지 예제에서는 배경 문자에 "."를 사용하여 쉽게 읽을 수 있도록 다시 돌아갑니다.)

두 벡터의 가중치가 1이면 결과는 평행 사변형처럼 나타납니다. 입력

.1.
...
1.0

출력으로 연결

X.1.
....
.1.0

입력 벡터가 동일 선상에있는 경우이 평행 사변형이 퇴화 될 수 있습니다.

0.1..1

출력으로 연결

0.1..1.X

결과 벡터가 입력 벡터 중 하나 또는 원점과 같을 수 있습니다. 이 경우 단순히 입력 문자를 덮어 씁니다. 예를 들어, 입력

..2.0.1...

출력을 산출

..X.0.1...

(입력 및 / 또는 출력에서 ​​선행 및 후행 기간을 삭제할 수 있음). 입력

.....3
......
...0..
......
......
2.....

출력을 산출

.....3
......
...X..
......
......
2.....

마지막으로 입력

90
.8

출력을 산출

........90
.........8
..........
..........
..........
..........
..........
..........
X.........

1
PPCG에 오신 것을 환영합니다! 좋은 첫 번째 도전.
AdmBorkBork

@TimmyD 환영과 격려에 감사드립니다 :)
Greg Martin

1
마지막으로, 다른 사람들이 그것을 가져올 것이라고 확신하기 때문에 상당한 양의 코드 덩어리가 입력의 구문을 분석하기 때문에 카멜레온 도전에 가까워 질 것입니다.
AdmBorkBork

입력 또는 올바른 출력의 행 / 열 수에 제한이 있습니까?
Sparr

@TimmyD 가중 합계에 대한 일반 공식을 추가했으며 두 입력 형식 중 하나라도 좋습니다. 나는 이것이 카멜레온 도전에 가깝다는 것에 동의한다 (그러나 나는 어떤 언어 (들)이 문제를 해결하기 위해 보드에서 직접 "걸을 수있는"능력을 갖기를 바랐다); 그러나 샌드 박스에 대한 피드백은 마이너스보다 약간 더 긍정적이어서 함께 진행하기로 결정했습니다.
Greg Martin

답변:


7

MATL , 48 바이트

tZyyX:UX>*Yat48-tt0>*3#fbbhb~2#fh-*s7M+'X'wZ}4$(

배경 문자는 공백입니다. 입력은 세미콜론으로 구분 된 행이있는 2D 문자 배열입니다. 따라서 테스트 사례에는 각각의 입력이 있습니다.

['    2'; ' 0   '; '   3 ']
[' 1 '; '   '; '1 0']
['0 1  1']
['  2 0 1   ']
['     3'; '      '; '   0  '; '      '; '      '; '2     ']
['90'; ' 8']

출력에는 많은 양의 패딩 공백이 포함됩니다.

온라인으로 사용해보십시오!


2

파이썬 3, 374 355 바이트

패딩에 매우 관대 한 세련되지 않은 파이썬 솔루션 (최대 체스 판 거리 사용). 입력은 행이 파이프로 분리되는 단일 행입니다. (알고리즘은 개행 문자 나 EOF가 아닌 영숫자가 아닌 것을 쉽게 사용할 수 있지만). 영숫자가 아닌 것 또는 | 입력 패딩에 사용되며 출력 패딩에는 마침표가 사용됩니다. 더 노련한 파이썬 골퍼의 피드백과 개선에 감사드립니다.

편집 : @TheBikingViking 덕분에 일부 개선되었습니다. 패딩으로 충분히 관대하지 않았기 때문에 더 많은 마진을 추가했습니다.

s=input()
l=[len(s),1+s.find('|')]['|'in s]
P=sorted([int(c),i%l,i//l]for i,c in enumerate(s)if c.isalnum())
L=X=Y=0
P[0][0]=-sum(p[0]for p in P)
for w,x,y in P:L=max(abs(x),abs(y),L);X+=x*w;Y+=y*w
P+=[['X',P[0][1]+X,P[0][2]+Y]]
P[0][0]=0
L=2*max(abs(X),abs(Y),L)
S=[2*L*["."]for _ in[0]*2*L]
for w,x,y in P:S[L+y][L+x]=str(w)
for s in S:print(''.join(s))

좋은 대답입니다! 파이썬 팁을 살펴보십시오 . 몇 가지 조언 : 1. 일부 기능이 다르기 때문에 Python 2/3을 사용했는지 여부를 지정하는 것이 좋습니다. 2 줄에서 [a,b][condition]대신 할 수 있습니다 . 제너레이터 문을 포함한 모든 반복자를 사용하므로 대괄호 바깥 쪽 쌍을 삭제할 수 있습니다. 3. 대신 작동해야합니다 . b if condition else csortedzip(p)p[0] for p in P
TheBikingViking

4. 7 번 라인 P+=[stuff]대신에 할 수 있습니다 P.append([stuff]). 5. ["."]대신에 list(".")하세요. (3. zip(p)[0]
이었어 야했다

죄송합니다, 자본해야한다 Pzip.
TheBikingViking

5. S=[stuff]*2*L10 행에서 할 수 있어야합니다 .
TheBikingViking

[1] 좋은 점은 파이썬 버전을 추가 할 것입니다. [2] 좋은 패턴이지만 작동하지 않습니다 index(아무것도 발견 되지 않은 오류). find그래도 작동 합니다. [레. 정렬] 감사합니다 sorted.를 추가 할 때 제거하지 못했습니다 . [3] zip (* P) ​​[0]은 Python 3에서 작동하지 않습니다 (zip 객체는 색인을 생성 할 수 없음). [4] P + = [stuff]는 작동하지만 P + = [stuff]는 작동하지 않습니다. [5] 감사합니다. [다른 5 명] 작동하지 않습니다. 참조가 아닌 새로운 목록이 필요합니다.
algmyr

2

자바 스크립트, 534 528 502 바이트

n="indexOf"
J="join"
B=X=>X.split(O)
O='\n'
w=i[n](O)+1
h=B(i).length
Z=(X,Y,R)=>{C[R]+=X-1;return Array(X)[J](Y)}
C=[0,0,0]
G=(X,E,T,U,R)=>X>0&E>=0?Z(X+E+1+T,U,R):""
o=i[n]("0")
L=X=>Math.floor(X/(w-1))
l=L(o)
c=o%w
x=y=0
j=i
for(z="1";z<="9";z++){while(p=~j[n](z)){j=j.replace(z," ")
x+=~p%w-l
y+=L(~p)-c}}
I=B(i).map(X=>G(-x,-l,0," ",0)+X+G(x,l-w+2,0," ",2))
N=Z(I[0].length+1," ",2)
A=B(G(-y,-c,0,N+O,1)+I[J](O)+G(y,c-h,1,O+N,2))
M=y+c+C[1]
O=""
m=B(A[M])
m[x+l+C[0]/h]="x"
A[M]=m[J]("")
A[J]("\n")

패딩이 최적입니다. 이 프로그램은 i가 원시 문자열을 포함하고 행을 \n문자로 구분한다고 가정합니다 . 패딩은 공백으로 수행되며 결과 문자는 소문자 x입니다.

이것이 코드 골프에 대한 첫 번째 시도입니다.

기술적 내용 :-JavaScript 문자열은 불변이기 때문에 결과 문자를 고려하기 위해 프로그램의 크기가 대략 두 배가되었고 복잡성이 크게 증가했습니다.


라인 별 설명 :

n="indexOf"
J="join"
B=X=>X.split(O)

나는 그것들을 많이 사용하므로 문자열에 저장하면 공간이 절약됩니다. 아래에서 split함수의 별칭을 만들었습니다. 하나의 인수 만 필요하고 다른 하나는 일정하기 때문입니다. 들어 indexOfjoin, 그것은 그러나 더 이상했을 것이다.

O='\n'
w=i[n](O)+1
h=B(i).length

여기서 복잡한 것은 없지만 초기 배열의 너비와 높이를 읽습니다. 의 i[n]액세스 는 다르게 처리되는 indexOf반면 을 사용하는 것에주의하십시오 split.

Z=(X,Y,R)=>{C[R]+=X-1;return Array(X)[J](Y)}

재미있어지고 있습니다. 이 함수는 기본적으로 J-1에 문자열 X를 연결하여 반환합니다. 패딩을위한 공백 문자열을 생성하는 데 사용됩니다.

C=[0,0,0]

이 배열은 패딩에 의해 추가 된 행과 열의 수를 포함합니다 (첫 번째 경우에는 인수 h만큼). 마지막 셀은 정크 셀이므로 아래 함수에서 추가 인수가 발생하지 않습니다.

G=(X,E,T,U,R)=>X>0&E>=0?Z(X+E+1+T,U,R):""

이 함수만으로도 패딩 (라인과 열 모두)을 처리 할 수 ​​있습니다. 결과 벡터의 좌표 (X)와 생성 할 행 / 열 수 (E)를 기준으로 좌표를 생성해야하는지 여부를 결정합니다. 이것은 X+E+1+T약간의 공간을 절약하기위한 트릭 일뿐 U입니다. 채우는 문자열 (열 공간과 줄 전체 줄)이며 다시 돌아갑니다 R. 이 함수는 기본적으로 줄의 경우 해당 줄의 시작 또는 끝에서 필요한 패딩을 반환하고 열의 경우 원래 줄 앞이나 뒤에 필요한 패딩 줄을 반환합니다.

o=i[n]("0")
L=X=>Math.floor(X/(w-1))
l=L(o)
c=o%w

여기서 원점의 ​​위치를 ​​읽고 좌표를 검색합니다. L은 인덱스를 줄 번호로 변환하는 함수입니다.

x=y=0
j=i
for(z="1";z<="9";z++){
    while(p=~j[n](z)){
        j=j.replace(z," ")
        x+=~p%w-l
        y+=L(~p)-c
    }
}

이것을 읽기 쉽도록 공백을 추가했습니다. 여기서 일어나는 것은 가능한 각 숫자에 대해 원래 문자열에서 계속 찾습니다. 이 ~트릭은 Javascript에서 비교적 일반적입니다. 비트 NOT 연산자이지만 여기서 중요한 것은 ~-1==0루프의 끝을 테스트 할 수있게하는 것입니다. 그런 다음 문자열에서 문자를 지우면 (그래서 사본을 만든 이유) 필요한만큼 검색을 계속할 수 있습니다. 그런 다음 (x, y)간단한 빼기를 사용하여에 벡터의 좌표를 추가합니다 .

I=B(i).map(X=>G(-x,-l,0," ",0)+X+G(x,l-w+2,0," ",2))

여기에서 원래 문자열을 줄로 나누고 각 줄마다 줄 G전후에 패딩을 생성하는 호출 합니다. 등은 l-w+2간단한 색인 계산에서 나옵니다. 패딩을 추가 해야하는지 여부를 테스트 할 수 있습니다. 예를 들어 if x>0x+l-w+1>0이면 (x+l-w+1)+1줄 뒤에 공백을 추가해야합니다. 이 ( +x가) 첫 번째 매개 변수로 제거 X+E+1+T되어의 정의에 사용되었습니다 G.

첫 번째 문자와 열에 대해서도 비슷한 작업이 수행됩니다. 여기에는 하나의 함수 만 사용할 수있는 많은 인수 분해가 있습니다. 마지막 매개 변수에 유의하십시오. 첫 번째 경우, C[0]각 줄의 시작 부분에 몇 개의 열을 추가했는지 나중에 알 수 있도록 작성하고 싶습니다 . 결과 문자의 최종 위치를 검색 할 수 있습니다. 그러나 원래 줄 뒤에 추가 된 열은 신경 쓰지 않으므로 두 번째 호출 은 사용되지 않는 G정크 셀 에 씁니다 C[2].

N=Z(I[0].length+1," ",2)

여기에서는 단순히 새로운 길이의 줄을 읽고 그로부터 한 줄의 공백을 만듭니다. 세로 패딩을 만드는 데 사용됩니다.

A=B(G(-y,-c,0,N+O,1)+I[J](O)+G(y,c-h,1,O+N,2))

위의 두 줄과 동일합니다. 유일한 차이점은 C[1]이번에 쓰고 구분 기호 N+O와를 사용하는 것 O+N입니다. 그 기억 O개행이며, N공간의 라인입니다. 그런 다음 B결과를 다시 나누기 위해 적용 합니다 (결과 문자를 포함하는 줄을 검색하여 편집해야 함).

M=y+c+C[1]

결과 문자의 세로 인덱스입니다.

O=""
m=B(A[M])
m[x+l+C[0]/h]="x"

여기서는 O적절한 줄을 문자 배열로 나눌 수 있도록 수정 해야합니다. JavaScript 문자열은 변경할 수 없기 때문입니다. 문자열을 편집하는 유일한 방법은 문자열을 배열로 변환하고 (여기서 내가하고있는 일) 올바른 위치에서 편집하고 문자열을 다시 결합하는 것입니다. 또한 함수는 초기 라인 당 한 번 호출 h되었기 때문에 요소에 유의하십시오 G.

A[M]=m[J]("")
A[J]("\n")

마지막으로 배열의 새 문자열을 바꾸고 문자열에 다시 결합합니다. 우후!

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