Sp | Lit wo (r) dS, S (P) lit wO | rds


15

m | Y bR |는 We | iRd이다. F (o) RT (h) E La | sT fi (v) e YE | ars O | R s | o, (I) ha (a) lf wh | En의 C (u) T wO | rds (I) s (e) e Th | em. 내가 시작하기 시작했을 때, 그것은 거의 노력을 기울였다-B (u) TI 거의 cou (l) dn't N (o) T d | o 그것. N (o) w, 나는 머리 뒤로, d (n) d는 거의 그것을 보지 못했다. 그러나 나는 이것이 큰 도전이라고 생각했다.

정의

이 도전을 위해, 각 문자는 산세 리프 글꼴로 너비를 판단하여 점수를 매 깁니다. 이 너비를 사용하여 단어를 같은 너비의 두 반쪽으로 자릅니다. 이 챌린지에서 사용할 문자는 소문자와 대문자, 아포스트로피 및 하이픈으로 된 알파벳입니다.

Width  Characters
1      i l I '
2      f j r t -
3      a b c d e g h k n o p q s u v x y z
4      m w A B C D E F G H J K L N O P Q R S T U V X Y Z
5      M W

설명과 테스트 사례에서 |단어를 반으로 잘 나눌 수있는 위치를 나타냅니다. (그리고 )편지의 양쪽에 그 편지가 깨끗한 분할을 만들 반으로 분할됩니다 것을 나타냅니다.

입력

입력은 단일 "단어"로 구성됩니다 (사전에있을 필요는 없음). 원하는 텍스트 입력 (문자열, 문자 배열 등)에이 단어를 사용할 수 있습니다. 이 단어에는 문자 ', 및 -(위 표 참조) 만 포함됩니다 . 이 단어로 무엇을하는지 (아래 참조), 입력 사례는 개발자의 판단에 따릅니다. 필요한 경우 후행 줄 바꿈이 허용됩니다.

작업

모든 입력 형식 (가능한 모든 대문자 또는 소문자 위치의 모든 문자)을 순열하십시오. 예를 들어 input it's의 경우 아래는 모든 순열입니다.

it's
it'S
iT's
iT'S
It's
It'S
IT's
IT'S

단어의 순열을 반으로 나누려면 단어의 한쪽에있는 점이 단어의 다른쪽에있는 점과 같아야합니다. 그러나 두 짝수 부분 사이에 편지가 붙어 있으면 편지를 반으로 잘릴 수도 있습니다.

"반"이 문자열의 절반으로 이동했다는 것을 의미하지는 않습니다. "반"은 양쪽의 점이 동일 함을 의미합니다.

예 :

W5 점입니다. i1 포인트입니다. 순열 Wiiiii을 반으로 나누면의 W | iiiii양쪽에 5 개의 점이 생깁니다 |.

T3 점입니다. 순열 TTTT을 반으로 나누면의 TT | TT양쪽에 6 개의 점이 생깁니다 |.

w4 점입니다. a는 3 점입니다. 순열 waw을 반으로 나누면 양변 에 w (a) w5.5 점이 붙습니다. 점은 반으로 나뉘어져 a있으므로 양쪽으로 분산됩니다 a.

산출

출력값은 입력 값의 고유 순열 수의 정수이며 정수로 반으로 나눌 수 있습니다. 필요한 경우 후행 줄 바꿈이 허용됩니다.

테스트 사례

테스트 사례에 대한 입력의 모든 유효한 순열을 출력합니다. 이는 귀하를위한 사양의 일부가 아님을 기억하십시오.

내 중간 출력에서 ​​숫자는 위의 문자의 포인트 값을 나타내므로 출력을 조금 더 쉽게 볼 수 있습니다.

Input: a
( a ) 
  3   
( A ) 
  4   
Output: 2

Input: in
Output: 0

Input: ab
A | B 
4   4 
a | b 
3   3 
Output: 2

Input: abc
A ( B ) C 
4   4   4 
A ( b ) C 
4   3   4 
a ( B ) c 
3   4   3 
a ( b ) c 
3   3   3 
Output: 4

Input: will
W ( I ) L l 
5   1   4 1 
W ( I ) l L 
5   1   1 4 
W ( i ) L l 
5   1   4 1 
W ( i ) l L 
5   1   1 4 
w I | L l 
4 1   4 1 
w I | l L 
4 1   1 4 
w i | L l 
4 1   4 1 
w i | l L 
4 1   1 4 
Output: 8

Input: stephen
S T E ( P ) H E N 
4 4 4   4   4 4 4 
S T E ( p ) H E N 
4 4 4   3   4 4 4 
S T E | p h e n 
4 4 4   3 3 3 3 
S T e ( P ) H E n 
4 4 3   4   4 4 3 
S T e ( P ) H e N 
4 4 3   4   4 3 4 
S T e ( P ) h E N 
4 4 3   4   3 4 4 
S T e ( p ) H E n 
4 4 3   3   4 4 3 
S T e ( p ) H e N 
4 4 3   3   4 3 4 
S T e ( p ) h E N 
4 4 3   3   3 4 4 
S t E ( P ) H e n 
4 2 4   4   4 3 3 
S t E ( P ) h E n 
4 2 4   4   3 4 3 
S t E ( P ) h e N 
4 2 4   4   3 3 4 
S t E ( p ) H e n 
4 2 4   3   4 3 3 
S t E ( p ) h E n 
4 2 4   3   3 4 3 
S t E ( p ) h e N 
4 2 4   3   3 3 4 
S t e ( P ) h e n 
4 2 3   4   3 3 3 
S t e p | H E N 
4 2 3 3   4 4 4 
S t e ( p ) h e n 
4 2 3   3   3 3 3 
s T E ( P ) H E n 
3 4 4   4   4 4 3 
s T E ( P ) H e N 
3 4 4   4   4 3 4 
s T E ( P ) h E N 
3 4 4   4   3 4 4 
s T E ( p ) H E n 
3 4 4   3   4 4 3 
s T E ( p ) H e N 
3 4 4   3   4 3 4 
s T E ( p ) h E N 
3 4 4   3   3 4 4 
s T e ( P ) H e n 
3 4 3   4   4 3 3 
s T e ( P ) h E n 
3 4 3   4   3 4 3 
s T e ( P ) h e N 
3 4 3   4   3 3 4 
s T e ( p ) H e n 
3 4 3   3   4 3 3 
s T e ( p ) h E n 
3 4 3   3   3 4 3 
s T e ( p ) h e N 
3 4 3   3   3 3 4 
s t E ( P ) h e n 
3 2 4   4   3 3 3 
s t E p | H E N 
3 2 4 3   4 4 4 
s t E ( p ) h e n 
3 2 4   3   3 3 3 
s t e P | H E N 
3 2 3 4   4 4 4 
s t e p | H E n 
3 2 3 3   4 4 3 
s t e p | H e N 
3 2 3 3   4 3 4 
s t e p | h E N 
3 2 3 3   3 4 4 
Output: 37

Input: splitwords
S P L I T | W O r d s 
4 4 4 1 4   5 4 2 3 3 
<snip>
s p l i t w | o R d S 
3 3 1 1 2 4   3 4 3 4 
Output: 228

Input: 'a-r
' a ( - ) R 
1 3   2   4 
' a | - r 
1 3   2 2 
Output: 2

Input: '''''-
' ' ' ( ' ) ' - 
1 1 1   1   1 2 
Output: 1

승리

이것은 이므로 바이트 단위의 최단 답변이 이깁니다. 모든 테스트 사례 (최대 10 자까지의 모든 입력)를 적절한 시간 내에 출력 할 수 있어야합니다. 인위적으로 뚜껑을 닫지 마십시오.

하사품

이것이 가능한 영역인지는 모르겠습니다. 그러나 당신은 골퍼입니다-당신은 담당자를 위해 무엇이든 할 것입니다. 나는 antidisestablishmentarianism평균 컴퓨터 (일명 광산)에서 15 초 이내에 올바른 출력을 출력하는 프로그램에 대해 200 회 현상금을 제공합니다 (기본적으로 불가능한 것처럼이 현상금 조건이 충족되면 시작합니다 ). 이 테스트 케이스는 어떤 식 으로든 하드 코딩되어서는 안됩니다.

@DigitalTrauma가 내 현상금을 분쇄하여 2 초 안에 올랐습니다. 여기 에서 그의 답변을 확인 하십시오 .


2
@MackenzieMcClane은 5를 제외하고 2 ^ 23 = 8,388,608로 줄였습니다.
Jonathan Allan

2
antidisestablishmentarianism(골프가 아닌)의 첫 번째 숫자 는 83307040(그리고 모든 테스트 사례와 일치)이지만 랩톱에서 ~ 37 초가 걸립니다 (Python이라고 생각합니다). 누구도 그것을 계산합니까?
Jonathan Allan


8
내 뇌가 이상해 당신은 바로 이곳에 있습니다
Luis Mendo

6
나는 똑같이하려고하지 않아야합니다. 나는 똑같이하려고하지 않았다. n (o) tt (r) yt | ot | h (h) e sa | me를 표시했습니다. O | h cr | ap ...
Arnauld

답변:


8

Pyth , 75 74 73 70 바이트

lfsm} sT-Bysded._Tm.n] d * Fmm? k | qd \ i + 4} d "mw"|} d "il '"h |} d "fjrt-"+ 2} d "mw"-2 } d " ' 
-lfsm} sT-Bysded._Tm.n] d * Fmm? k | qd \ i + 4} d"mw "| x} Ld + c"mw il'fjrt- ") G1 4-2} d " ' 
-lfsm} sT-Bysded._Tm.n] d * Fm <, | x} Ld + c"mw il'fjrt- ") G1 4 | qd \ i + 4} d"mw "-2} d " '-
lfsm} sT-Bysded._Tm.n] d * Fm <, | x} Ld + c "mw il 'fjrt-") G1 4 | qd \ i + 4} d "mw"h} dG

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

하나님의 사랑을 antidisestablishmentarianism위해 통역사 에게도 시도하지 마십시오 . 당신은 그것을 충돌합니다.

설명

lfsm}sT-Bysded._Tm.n]d*Fm<,|x}Ld+c"mw il' fjrt-")G1 4|qd\i+4}d"mw"h}dG

이 코드를 X 부분으로 나누겠습니다.

첫 번째 부분 : 사례 별 버전 생성 및 값에 매핑

m<,|x}Ld+c"mw il' fjrt-")G1 4|qd\i+4}d"mw"h}dG

여기서 명확하게하자. 에서 어떤 과정의 일부가 대문자 글자입니다. 대문자 하나를 사용하지 않고 하나의 문자를 두 개의 값 (및 문장 부호를 하나의 값으로)으로 매핑하면됩니다. 두 개의 값이 필요한 문자와 하나의 문자가 필요한 문자를 결정합니다.

m<,|x}Ld+c"mw il' fjrt-")G1 4|qd\i+4}d"mw"h}dGQ  Q implicitly appended
m                                             Q  for d in Q:
                                           }dG       d in alphabet?
                                          h          +1 (T/F as 1/0)
 <   take the first ^ elements of the following array
     for d in alphabet, it will take 2 elements;
     for d being ' or -, it will take 1 element.
  ,          pair up the following two values
   |x}Ld+c"mw il' fjrt-")G1 4                  this is the first value
                             |qd\i+4}d"mw"    this is the second value

보시다시피 첫 번째 부분조차 너무 깁니다.

첫 번째 값은 '및 을 포함하는 소문자 버전 -입니다. 두 번째 값은 대문자 버전 '이며- 적용되지 않습니다.

첫 번째 값 :

|x}Ld+c"mw il' fjrt-")G1 4
       "mw il' fjrt-"        does what it says on the tin
      c              )       split on spaces, creating an
                             array with three elements
     +                G      append another element, which
                             is the alphabet, as a fail-safe;
                             now the array has 4 elements
  }Ld                        check if d is in each array
                             as with above, True becomes 1
                             and False becomes 0 (T/F as 1/0)
 x                     1     find the first occurrence of 1
|                        4   logical or with 4. If it was 0,
                             it would become 4 now.

첫 번째 문자열은 "mw"인덱스 0에 포함 됩니다. 값이 4이며 논리 또는 필요가 설명되어 있습니다. Pyth는 0- 인덱싱을 사용합니다. 또한 앞에있는 공백은와 4구분해야합니다 1.

두 번째 값 (대문자) :

|qd\i+4}d"mw"
 qd\i          d=="i"
|              logical OR
       }d"mw"  is d in "mw"? That is, is d "m" or "w"?
     +4        +4

경우 d이며 "i", 그것은 제공 1하는 첫 번째 단계에. 그렇지 않으면 계속됩니다. 경우 d이다 "m"또는 "w"다음 세 번째 단계는 제공 1하도록 첨가되는, 4수득 5. 경우 d없는 "m"또는 "w", 다음 세 번째 단계는 제공 0에 부가 된, 4수득4 .

두 번째 부분 : 작업 완료

lfsm}sT-Bysded._Tm.n]d*F

이것은 기술적으로 두 번째 부분과 분리되지 않은 첫 번째 부분 앞에 붙습니다 (여전히 하나의 명령 임). 따라서 첫 번째 부분의 값이 오른쪽으로 전달됩니다.

요약 : 첫 번째 부분에서 문자를 가능한 값 (문자는 소문자와 대문자, 두 문장 부호는 하나만)에 매핑했습니다. 입력의 "ab"경우 얻을 수 [[3,4],[3,4]]있습니다.

서로 다른 사례 버전을 생성하기 위해 (첫 번째 부분에서 수행했지만 오버플로가 발생 함) 카티 전 곱을 반복적으로 사용한 다음 결과를 평평하게합니다. 데카르트 곱은 우리에게 배열을 제공하지 않으며, 평 평화 명령 ( .n)이 오버플로되어 숫자에 이상한 결과를 초래하기 때문에 하나의 문자 (첫 번째 테스트 케이스) 만있을 때 문제가 발생 합니다. 이 문제를 어떻게 우회했는지 살펴 보겠습니다.

lfsm}sT-Bysded._Tm.n]d*F
                      *F  reduce by Cartesian product
                 m   d    for d in each unflattened version:
                    ]         [d] (wrap in array)
                  .n          flatten
 f                filter for resulting arrays as T
              ._T all prefixes of T
   m              for d in each prefix:
          sd          find the sum of d
         y            double
       -B   ed        [above, above - last element of d]
    }sT               is the sum of T in the above array of 2 elements?
  s               sum the 1/0 generated in each prefix
                  any non-zero value is regarded as truthy
l                 length

중간에 분할 된 경우 | 에서로 나누면 접두어의 합계가 합계의 두 배가됩니다.

()나누면 접두사 합계에서 2를 뺀 값을 괄호로 묶은 값이 합계의 합계가됩니다.


예, 시간이있을 때 (나는 바쁜 일정에 대해 사과드립니다.)
Leaky Nun

11

c, 378 바이트; 약 0.6 초antidisestablishmentarianism

답변이 업데이트되었습니다 . 나는 약 JonathanAllan의 코멘트 @ 읽어 i들, 먼저 I에서이 최적화를 이해하지 못했지만, 지금은 모두 이후 볼 iI1의 폭을 가지고, 우리는 한 번만 유효성을 검사하는 데 두 번 관련 순열을 계산 할 수 있습니다. 이전에는 내 솔루션에서 여러 스레드를 사용하여 여러 CPU에로드를 분산 시켰으며 2 28 을 모두 처리 할 수있었습니다. 내 컴퓨터에서 가능성 . 이제 i최적화를 통해 스레드를 망칠 필요가 없습니다. 단일 스레드가 시간 제한 내에서 쉽게 작업을 수행합니다.

더 이상 골치 아프지 않은 c 함수 :

char m[128]={[39]=10,[45]=20};f(s,l,p)char *s;{m[65]?:bcopy("PPPPPPPPPPPdPPPPPPPPPdPPP      <<<<<(<<(<P<<<<(<(<<P<<<",m+65,58);int g,h,u=0,v=0,x=0,y=0,c=0;if(p<l){g=s[p];if(g>64&&g-'i'){s[p]-=32;c+=f(s,l,p+1);}s[p]=g;c+=((g=='i')+1)*f(s,l,p+1);}else{for(l--,p=0,g=m[s[p]],h=m[s[l]];p<=l;){y=v;x=u;if(u+g>v+h){v+=h;h=m[s[--l]];}else{u+=g;g=m[s[++p]];}}c=u==v||y==x;}return c;}

재귀 함수 f 는 입력 문자열에 대한 포인터, 문자열 길이 및 처리를 시작할 문자열의 오프셋 (최상위 호출의 경우 0이어야 함)의 3 가지 매개 변수를 사용합니다. 이 함수는 순열 수를 반환합니다.

온라인으로 사용해보십시오 . TIO는 일반적으로 모든 테스트 케이스 (antidisestablishmentarianism 2 초 미만을 .

되는 문자열의 일부 unprintables가있는 것으로 도시 bcopy()에 에드m[] . TIO가이를 올바르게 처리하는 것 같습니다.

언 골프 드 :

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>

int width_tbl[] = {
    ['\''] = 1,
    ['-'] = 2,
    ['A'] = 4,4,4,4,4,4,4,4,1,4,4,4,5,4,4,4,4,4,4,4,4,4,5,4,4,4,
    ['a'] = 3,3,3,3,3,2,3,3,1,2,3,1,4,3,3,3,3,2,3,2,3,3,4,3,3,3
};

int
f (char *str, int len, int pos) {
    int lidx, ridx;
    int tot_width = 0;
    int lwidth, rwidth;
    int tot_lwidth = 0, tot_rwidth = 0;
    int prev_tot_lwidth = 0, prev_tot_rwidth = 0;
    char tmp;
    int perm_cnt = 0;

    if (pos < len) {
        tmp = str[pos];
        if (isalpha(tmp) && (tmp != 'i')) {
            str[pos] = toupper(str[pos]);
            perm_cnt += f(str, len, pos+1);
        }
        str[pos] = tmp;
        perm_cnt += ((tmp == 'i') + 1) * f(str, len, pos+1);
    } else {
        //puts(str);
        lidx = 0;
        ridx = len - 1;
        lwidth = width_tbl[str[lidx]];
        rwidth = width_tbl[str[ridx]];
        while (lidx <= ridx) {
            prev_tot_rwidth = tot_rwidth;
            prev_tot_lwidth = tot_lwidth;
            if (tot_lwidth + lwidth > tot_rwidth + rwidth) {
                tot_rwidth += rwidth;
                rwidth = width_tbl[str[--ridx]];
            } else {
                tot_lwidth += lwidth;
                lwidth = width_tbl[str[++lidx]];
            }
        }
        if (tot_lwidth == tot_rwidth) {
            perm_cnt = 1;
        } else if (prev_tot_rwidth == prev_tot_lwidth) {
            perm_cnt = 1;
        }
    }
    return perm_cnt;
}


int main (int argc, char **argv) {
    int i;
    int perm_cnt;

    if (argc > 0) {
        char *str = strdup(argv[1]);
        assert(str);

        perm_cnt = f(str, strlen(str), 0);

        printf("n = %d\n", perm_cnt);
    }

    return 0;
}

MacOS 10.12.4를 실행하는 2015 년 중반 MacBook Pro가 있습니다. 컴파일러는 기본 MacOS 클랜입니다. 나는 컴파일하고있다 :

cc splitwords.c -O2 -o splitwords

다음을 포함하여 모든 테스트 케이스를 실행 antidisestablishmentarianism하면 다음이 제공됩니다.

$ time ./splitwords
Testcase "a": n = 2
Testcase "in": n = 0
Testcase "ab": n = 2
Testcase "abc": n = 4
Testcase "will": n = 8
Testcase "stephen": n = 37
Testcase "splitwords": n = 228
Testcase "'a-r": n = 2
Testcase "'''''-": n = 1
Testcase "antidisestablishmentarianism": n = 83307040

real    0m0.573s
user    0m0.564s
sys 0m0.003s
$

이것은 결코 최적이 아닙니다. 이 알고리즘은 모든 가능성을 통해 무차별 대입 (모듈로 i-위의 주석 참조)하고 기준에 따라 분리 될 수있는 단어를 계산합니다.


잘 했어, 정말 내가이 편지의 7 개 클래스의 고정 효과를 사용하여, O (N)에 결과를 평가하는 아마 가능하다고 생각, i, -, ', l, mw, fjrt,와 abcdeghknopqsuvxyz,하지만의 응용 프로그램 걸릴 폴리 -A 열거 정리 (또는 동등한 조합 열거 방법), 나는 잘 정통하지 않습니다.
Jonathan Allan

내가 예상 한대로 내 기대를 무너 뜨렸다 이것은 당신이 재귀를 사용하는 방법입니다 :)
Stephen

1

자바 스크립트 (ES6), 199 169 167 바이트

입력 문자열이 소문자 일 것으로 예상합니다. 현상금이 너무 느립니다.

f=(s,r=[],t=R=0,i=3,x=parseInt("k1048cccctt"["i'l-fjrtmw".search(c=s[0])+1],36)+8>>i&7)=>x&&(c?(i&&f(s,r,t,0),f(s.slice(1),[x,...r],t+x)):R+=r.some(x=>t==x|!(t-=2*x)))

테스트 사례


1

C, 403 394 바이트,

고마워 Kevin!

r;char*g[]={"","ilI'","fjrt-","","mw","MW",0},**p,b[99];q(c){for(p=g;*p;p++)if(strchr(*p,c))return p-g;return c>='a'&&c<='z'?3:4;}f(char*w,int l){int i,n,c,t,x,y;if(*w){for(i=0;i<2;i++)x=tolower(*w),y=toupper(*w),!i||x!=y?b[l]=i%2?x:y,b[l+1]=0,f(w+1,l+1):0;}else{t=0;for(c=0;c<2;c++)for(i=0;i<l;i++){x=y=0;for(n=0;n<l;n++)c==0||n!=i?((n<i)?(x+=q(b[n])):(y+=q(b[n]))):0;t|=x==y;}r+=t;}return r;}

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

Ungolfed 코드 :

int getwidth(int c)
{
    char **p, *g[] = { "", "ilI'", "fjrt-", "", "mw", "MW", 0};
    for (p=g; *p; p++)
    {
        if (strchr(*p,c))
            return p-g;
    }
    return c >= 'a' && c <= 'z' ? 3 : 4;
}

int test(char* w, int l)
{
    int i, n, c, t, x, y;

    if (*w)
    {
        for (i=0;i<2; i++)
        {
            x = tolower(*w);
            y = toupper(*w);
            if (!i || x != y)
            {
                b[l] = i % 2 ? x : y;
                b[l + 1] = 0;
                test(w + 1, l+1);
            }
        }
    }
    else
    {
        t = 0;
        for (c=0; c<2; c++)
        {
            for (i=0; i<l; i++)
            {
                x = 0;
                y = 0;
                for (n=0; n<l; n++)
                {
                    if (c == 0 || n != i)
                    {
                        if (n < i)
                            x += getwidth(b[n]);
                        else
                            y += getwidth(b[n]);
                    }
                }
                t |= x == y;
            }
        }
        r += t;
    }
    return r;
}

당신은 약간의 공백이 여기에 골프 잊었 : f(char* w, int l){->f(char*w,int l){
케빈 Cruijssen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.