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


15

m | Y bR | ainはWe | iRdです。F(o)RT(h)E La | sT fi(v)e YE | ars O | R s | o、(I)ha | ve C(u)T wO | rds in h(a)lf wh | En (I)s(e)e Th | em。Wh | EN Do |を始めたので、To | oK a meN | TaLの努力-B(u)TIはほとんどN(o)Tではありません。N(o)w、私は私の頭の後ろにあります、a(n)dはほとんどありません|それはありません。しかし、これは大きな挑戦だと思いました。

定義

このチャレンジでは、サンセリフ体のフォントでの幅の判断に基づいて、各文字にポイントスコアが与えられます。この幅を使用して、単語を等しい幅の2つの半分にカットします。このチャレンジが使用する文字は、大文字と小文字のアルファベット、アポストロフィ、およびハイフンです。

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

単語の順列を半分に分割するには、単語の片側のポイントが単語の反対側のポイントと同じでなければなりません。ただし、2つの偶数セクションの間に文字が挟まっている場合は、文字をきれいに半分に切ることもできます。

「半分」とは、文字列の途中まで移動したことを意味しないことに注意してください。「ハーフ」とは、両側のポイントが等しいことを意味します。

例:

W5ポイントです。i1ポイントです。順列Wiiiiiを半分に分割すると、のW | iiiii各側に5つのポイントがあり|ます。

T3ポイントです。順列TTTTを半分に分割するTT | TTと、|ます。

w4ポイントです。aは3ポイントです。順列wawを半分に分割すると、w (a) w両側に5.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 repの報奨金を提供しています(この報奨金の条件が満たされると、私は基本的に不可能だと思います)。このテストケースは、いかなる方法でもハードコーディングしないでください。

@DigitalTraumaが私の賞金を粉砕し、2秒足らずで入りました。こちらで彼の答えをご覧ください


2
@MackenzieMcClaneは、5個の 'i'が2 ^ 23 = 8,388,608になることを除いて
ジョナサンアラン

2
antidisestablishmentarianism(ゴルフ以外の)の最初のカウントは83307040(およびすべてのテストケースに一致する)ですが、ラップトップで約37秒かかります(Pythonであることに注意してください)。誰もがそれをカウントしていますか?
ジョナサンアラン


8
私の脳は奇妙ですあなたは正しい場所にいます
ルイスメンドー

6
私は同じことをしようとするべきではありません。私は同じことをしようとしないでください。私はn(o)tt(r)yt | od | ot(h)e sa | meと言った。O | h cr | ap ...
アーナルド

回答:


8

Pyth75 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

ここで明確にしましょう。ありませんプロセスの一部の文字を大文字にしています。1つの文字を2つの値にマップする(および句読点を1つの値にマップする)だけで、大文字にする必要はありません。2つの値が必要な文字と、1つの値が必要な文字を決定します。

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

ご覧のとおり、最初の部分でも長すぎます。

最初の値は、小文字バージョンのためのものである'-。2番目の値は大文字バージョン用で'あり、使用-されません。

最初の値:

|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で、論理ORの必要性を説明しています。Pythは0インデックスを使用することに注意してください。また、の前のスペース4はから分離するためのもの1です。

2番目の値(大文字):

|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"、第3のステップは、与える1ために添加され、4与えます5。場合dではない"m"、または"w"、第3ステップでは、得られる0に添加され、4与えます4

第二部:仕事を成し遂げる

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

これは最初の部分の先頭に追加されますが、技術的には2番目の部分から分離されていません(1つのコマンドのままです)。したがって、最初の部分の値は右に渡されます。

要約:最初の部分では、文字を可能な値にマッピングしました(文字の小文字と大文字、2つの句読点の1つの値のみ)。入力用"ab"では、[[3,4],[3,4]]ます。

異なるケースバージョンを生成するには(最初の部分で行う必要がありますが、オーバーフローします)、デカルト積を繰り返し使用し、結果をフラット化します。デカルト積では配列が提供されず、flattenコマンド(最初のテストケース)がある場合に問題が発生します(.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倍になり、合計になります。

で分割される場合()、2倍になった接頭辞の合計から括弧内の値を引いたものが合計の合計になります。


はい、時間があれば。(忙しいスケジュール
リーキー修道女

11

c、378バイト。約0.6秒antidisestablishmentarianism

回答を更新しました。私はis に関する@JonathanAllanのコメントを読みましたが、最初はこの最適化を理解していませんでしたが、両方iI幅が1であるため、関連する順列を1回検証するだけで2回カウントできることがわかりました。以前は、私のソリューションでは複数のスレッドを使用して負荷を複数の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は、入力ストリングへのポインター、ストリングの長さ、および処理を開始するためのストリング内のオフセットの3つのパラメーターを取ります(トップレベル呼び出しの場合は0でなければなりません)。この関数は、順列の数を返します。

オンラインでお試しください。TIOは通常、すべてのテストケースを実行するようです(antidisestablishmentarianism2秒未満を含む)。

bcopy()edにされる文字列にはいくつかの印刷できないものがあることに注意してください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 clangです。私は次のものでコンパイルしています:

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-'lmwfjrt、そしてabcdeghknopqsuvxyz、それが適用かかるポリA列挙定理を(または同等の組み合わせ列挙法)、私はあまり詳しくありません。
ジョナサンアラン

私の期待通り、あなたは私の期待を破壊しました。これが、再帰の使用方法です:)
スティーブン

1

JavaScriptの(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バイト、

ありがとうケビン!

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;}

オンラインで試す

未ゴルフコード:

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){
ケビンクルーッセン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.