약어의 일반화


14

단어 목록과 약어를 입력하면 약어를 구성 할 수있는 패턴이 출력됩니다.

입력 예제를 보자.

potato ptao
puzzle pzze

예를 들어, 약어는 potatois ptao, 약어는 puzzle입니다 pzze.

얻기 위해 가능한 모든 방법을 고려 ptao에서가 potato. 가능한 한 가지 방법은 첫 번째, 세 번째, 네 번째 및 여섯 번째 글자를 취하는 것 1346입니다. 하지만 이후 to단어에 여러 번 표시, 거기에 생성하는 여러 다른 가능한 방법입니다 ptao으로부터는 potato: 1546, 1342,와 1542.

마찬가지로, 참고 pzze로부터 생성 될 수있는 puzzle의와 1336, 1346, 1436, 1446. 이 두 약어가 공통적으로 갖는 유일한 패턴은 1346; 따라서이 입력에 대한 출력이어야합니다. 여러 개의 가능한 패턴이 가능한 경우, 일부 또는 전부 (적어도 하나)를 출력 할 수 있습니다.

다음과 같이 가정 할 수 있습니다.

  • 입력 단어 및 약어에는 소문자 만 포함됩니다.

  • 입력에 하나 이상의 단어 / 약어 쌍이 있습니다.

  • 모든 약어가 해당 단어로 구성 될 수 있습니다.

  • 모든 약어를 형성하는 패턴은 항상 하나 이상 있습니다.

  • 각 단어의 최대 길이는 9 자입니다.

다음 중 하나로 입력 할 수 있습니다.

  • 튜플 등의 2 차원 배열 / 목록 / 배열 [[word, abbr], [word, abbr], ...]

  • 평평한 1 차원 배열 / 목록 [word, abbr, word, abbr, ...]

  • 소문자가 아닌 단일 문자로 구분되는 단일 문자열 "word abbr word abbr"

  • 해시 / 연관 배열 등 {word => abbr, word => abbr, ...}

이러한 입력 옵션 중 하나에서 단어 / abbr의 순서를 바꿀 수도 있습니다 (게시물의 입력 형식을 완전히 설명하십시오).

출력은 단일 숫자, 비 숫자로 구분 된 문자열 또는 배열 / 목록 / 튜플 / 등으로 제공 될 수 있습니다. 숫자.

이것은 이므로 바이트 단위의 가장 짧은 코드가 승리합니다.

테스트 사례 (여러 패턴이 작동하는 경우 ≥1 결과 만 출력해야 함) :

In                                Out
--------------------------------------------------------
potato ptao puzzle pzze         | 1346
aabbcc abc fddeef def           | 246
prgrmming prgmg puzzles pzzlz   | 14353
aaaaa a bbbb b ccc c dd d e e   | 1
aaaaa a bbbb b ccc c            | 1, 2, 3
abcxyz zbcyax                   | 623514
abcxyz acbbacbcbacbbac          | 132213232132213
potato ptao                     | 1346, 1546, 1342, 1542
a aaaaa                         | 11111

이해를 돕기 위해 약어 프로세스에서 문자의 순서를 바꿀 수 있습니까?
xnor

@xnor 여러 테스트 사례에서 볼 수 있듯이 정확합니다.
Doorknob

2D 어레이가 다른 방향을 가질 수 있습니까? 각 행이 아닌 각 열에는 한 쌍의 단어 / 약자가 포함됩니다.
Luis Mendo

@DonMuesli 아니요, 불가능합니다.
Doorknob

0 인덱싱을 사용할 수 있으므로 1346 대신 0235를 인쇄하십시오.
Denker

답변:


3

Pyth, 19 바이트

mhh@Fd.TmmxkmbhdedQ

여기 사용해보십시오!

다음 형식으로 목록을 가져옵니다.

[["word","abbr"],["word","abbr"],...]

1 요소 목록에 랩핑 된 0부터 시작하는 인덱스 목록으로 결과를 출력하는 대체 17 바이트 솔루션 :

m@Fd.TmmxkmbhdedQ

설명

예: [["potato", "ptao"],["puzzle", "pzze"]]

먼저 우리는 축약어의 모든 문자를 생성하는 단어의 모든 발생 색인 목록에 매핑합니다.

[[[0], [2, 4], [3], [1, 5]], [[0], [2, 3], [2, 3], [5]]]

그런 다음이 목록을 바꿉니다.

[[[0], [0]], [[2, 4], [2, 3]], [[3], [2, 3]], [[1, 5], [5]]]

따라서 각 약어의 각 문자 색인은 하나의 목록에 함께 있습니다.

그런 다음 모든 목록에서 하나의 공통 색인을 찾아야합니다.

[[0], [2], [3], [5]]

이것은 위의 대안 17 바이트 솔루션의 출력입니다. 그런 다음로 변환됩니다 [1,3,4,6].

코드 분석

mhh@Fd.TmmxkmbhdedQ # Q = 입력

d를 사용한 m Q # 맵 입력
        m ed # 각 abbrevation을 k로 매핑
            mbhd # 단어를 문자 목록으로 매핑
         mxk # 각 축약 문자를 색인 목록에 맵핑
      .T # 조옮김
    Fd # 모든 요소를 ​​접습니다
   @ # 및 존재시 필터
 hh # 결과의 첫 번째 요소를 가져 와서 증가

? dm바로 전에 삭제하지 못했습니다 @.
Doorknob

@Doorknob 할 수 있습니다. 그것을 발견해 주셔서 감사합니다!
Denker

3

MATL , 29 바이트

!"@Y:!=2#fX:wX:h]N$v1XQtv4#X>

입력은 다음 형식의 2D 배열입니다.

{'potato' 'ptao'; 'puzzle' 'pzze'}

온라인으로 사용해보십시오! ( 이 답변이 게시 된 후 언어 변경으로 인해 링크 된 코드에 일부 수정 사항이 포함되어 있습니다 )

!       % take input. Transpose
"       % for each column
  @Y:   %   push column. Unpack the two strings and push them onto the stack
  !     %   transpose second string
  =     %   matrix with all pairwise matchings of characters in word and abbreviation
  2#f   %   find row and col indices of those matchings
  X:    %   transform into column vector
  wX:   %   swap, transform into column vector
  h     %   concat into a two-col matrix
]       % end for
N$v     % concatenate all matrices containing the indices
1       % push 1
XQ      % build matrix adding 1 for each (row,col) index
tv      % concat vertically with itself, so that it has at least two rows.
        % This forces the following function to work on each col.
4#X>    % arg max of each col: position that produces a match in all pairs.
        % If there are several maximizers in each col this gives the first

이 코드에는 몇 가지 (그리고 긴!) 트릭이 필요했습니다.

  • find( f)로 생성 된 벡터의 방향이 입력 모양에 따라 변경되지 않도록합니다 . 이것들은 진술입니다 X:wX:: 두 출력을 열 벡터로 만듭니다.
  • min( X>) 함수 의 "싱글 톤이 아닌 첫 번째 치수에 따른 작업"기본 동작에 대응합니다 . 이것들은 다음과 같은 진술입니다 tv: 최소한 두 개의 행을 보장하기 위해 자체의 사본을 연결하십시오).

2

펄, 46 45 42 바이트

에 +1 포함 -p

STDIN에서 순차적 단어로 입력하십시오. 예 :

perl -p abbrev.pl
prgrmming
prgmg
puzzles
pzzlz

와 STDIN을 종료 ^D하거나 ^Z또는 무엇이든은 시스템에 필요한

abbrev.pl:

s#.#${${--$_.$.%2}.=$&}||=-$_#eg;$_ x=eof

설명

이 입력을 고려하십시오 (이 프로그램에 대한 실제 입력 방법이 아닌 개념적인 레이아웃).

potatoes     ptao
puzzle       pzze

프로그램은 열 ID에서 색인화 된 전체 문자열의 세로 열을 나타내는 문자열을 빌드합니다.

id1    pp     -> 1
id2    ou     -> 2
id3    tz     -> 3
id4    az     -> 4
...

약어의 경우에도 동일하지만 다른 ID를 사용합니다.

ID1    pp     -> 1
ID2    tz     -> 3
ID3    az     -> 4
ID4    oe     -> 6

-p옵션 을 사용하여 단어를 하나씩 암시 적으로 처리합니다 . 열 문자열은 반복 된 연결을 사용하여 구성되는 반면 각 단어는을 사용하여 이동 s#.# ...code.. #eg하므로 각 열은 반복 가능한 ID가 필요합니다. 열 번호에서 줄 번호 modulo 2를 뺀 값을 사용합니다. 열 번호 --$_는 현재 단어로 시작 a-z하여 숫자 컨텍스트에서 0으로 평가되는 것을 사용 하여 구성 할 수 있습니다 . 그래서 나는 얻는다 -1, -2, -3, .... 실제로 사용 1, 2, 3, ...하고 $_++싶었지만 일반 숫자 카운터 대신 펄 마법 문자열 증가를 트리거합니다. 나는 않습니다 사용할$_ 너무 많은 바이트를 차지하는 모든 루프에서 다른 변수를 0으로 초기화해야하기 때문에 다른 변수는 아닙니다.

줄 번호 모듈로 2는 전체 단어의 ID와 약어의 ID가 충돌하지 않도록하는 것입니다. 전체 단어의 길이가 같지 않기 때문에 전체 단어와 약어를 사용하여 하나의 문자열에서 열 번호가 결합 된 문자열을 넘어갈 수 없다는 점에 유의하십시오. 또한 전체 단어의 첫 번째 열의 수가 1이어야하기 때문에 약어 단어를 먼저 넣을 수 없습니다 (모두 길이가 동일합니다).

엄격하지 않은 참조를 통해 Perl 전역 네임 스페이스를 남용하여 열 문자열을 다음과 같이 구성합니다.

${--$_.$.%2}.=$&

다음으로 perl 전역 네임 스페이스를 다시 사용하여 각 열 문자열을 해당 문자열이 이미 표시된 첫 번째 열 번호 (위에 이미 표시된 매핑)에 매핑합니다 (그러나 이름이 충돌 할 수 없으므로 전역이 서로 간섭하지 않습니다).

${${--$_.$.%2}.=$&} ||= -$_

$_위에서 설명한 것처럼 열을으로 계산 하기 때문에 부정해야합니다 -1, -2, -3, .... ||=메이크업은 확인 만 주어진 컬럼의 첫 등장 그렇지 않으면 이전의 열 번호가 보존되어, 새로운 열 수를 가져옵니다 값으로 돌아왔다. 명세서에서 사전에 나타날 전체 단어에 열이 있음을 보장하기 때문에 이는 모든 약자에 대해 특히 발생합니다. 따라서 가장 짧은 축약어에서 각 문자는 모든 축약어의 열에 해당하는 전체 단어의 열 번호로 대체됩니다. 따라서 마지막 치환의 결과는 원하는 최종 결과입니다. 입력이 끝났을 경우에만 인쇄하십시오.

$_ x=eof

열이 아직 구성되지 않았거나 일부 단어가 더 짧고 전체 열 길이에 도달하지 않기 때문에 열 인덱스 할당은 불완전한 열에 대한 항목도 생성합니다. 모든 약식 단어에 필요한 열에 가능한 최대 길이 (현재 표시된 쌍의 수)를 갖는 전체 단어의 해당 열이 있으므로 이러한 추가 항목은 절대로 일치하지 않습니다.


1

하스켈, 74 바이트

import Data.List
foldl1 intersect.map(\(w,a)->mapM(`elemIndices`(' ':w))a)

입력 형식은 다음과 같은 문자열 쌍의 목록입니다.

*Main > foldl1 intersect.map(\(w,a)->mapM(`elemIndices`(' ':w))a)  $ [("potato","ptao"),("puzzle","pzze")]
[[1,3,4,6]]

작동 방식 : mapM(와 동일 sequence . map) 먼저 모든 쌍 (w,a)을 약어의 문자 ' ':색인 ("potato", "ptao") -> [[1],[3,5],[4],[2,6]]목록 목록으로 변환합니다 ( 예 : Haskell의 기본 0 기반 색인을 1 기반으로 수정). 그런 다음 모든 조합의 목록으로 바꿉니다. 위치에있는 요소는 예를 들어 하위 목록 i에서 가져옵니다 . 이러한 모든 목록 목록의 교차점을 찾습니다. i[[1,3,4,2],[1,3,4,6],[1,5,4,2],[1,5,4,6]]foldl1 intersect


0

ES6, 92 바이트

(w,a)=>[...a[0]].map((_,i)=>[...w[0]].reduce((r,_,j)=>w.some((s,k)=>s[j]!=a[k][i])?r:++j,0))

단어 배열과 약어 배열로 입력을 허용합니다. 1 기반 인덱스의 배열을 반환합니다 (2 바이트의 비용이 소요됩니다). 여러 솔루션의 경우 가장 높은 지수가 반환됩니다.


0

파이썬 3, 210 바이트

여기에서 최고 점수를 얻는 인상적인 대답은 아니지만, 이것은 내가 파이썬으로 해본 것 중 가장 미친 목록 이해 중 일부입니다. 이 접근법은 매우 단호합니다.

 def r(p):
    z=[[[1+t[0]for t in i[0]if l==t[1]]for l in i[1]]for i in[[list(enumerate(w[0])),w[1]]for w in p]]
    return[list(set.intersection(set(e),*[set(i[z[0].index(e)])for i in z[1:]]))[0]for e in z[0]]

이 함수는 입력을 항상 다음과 같은 문자열 2 차원 배열로 예상하고 [[word, abbr],...]정수 목록을 반환합니다.

추신 : 곧 자세한 설명

PS2 : 추가 골프 제안을 환영합니다!

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