같은 점수를 가진 부분으로 단어를 나눕니다.


9

A = 1, B = 2 ... Z = 26이고 단어의 값이 이러한 문자 값의 합이라고 가정하면 일부 단어를 같은 값을 갖도록 두 조각으로 나눌 수 있습니다.

예를 들어, "wordsplit"은 o + r + d + s + l = w + p + i + t이므로 ordsl wpit의 두 부분으로 나눌 수 있습니다.

이것은 컴퓨팅 교사가 우리에게했던 도전이었습니다. 그것은 오래된 Lionhead Studios의 도전입니다. 나는 그것을 파이썬으로 해결했으며 곧 답변을 게시 할 것입니다.

도전 과제 : 동일한 점수를 가진 가능한 모든 스플릿을 나열 할 수있는 가장 짧은 프로그램 . 각 문자 그룹마다 하나씩 만 나열하면됩니다. 예를 들어 ordsl wpit은 rdosl wtip과 같습니다. 단어 순서대로 나열하는 것이 더 쉽습니다.

보너스:

  • 두 단어가 모두 유효한 영어 단어 인 경우 (또는 문자의 일부 순열이있는) 쌍을 강조 표시하는 경우 어떤 종류의 단어 목록을 사용하십시오. (이 방법은 각각 또는 다른 방법 옆에 별표를 표시하여 수행 할 수 있지만 명확하게하십시오.)
  • 중복 제거 옵션 추가 (기본값이 아님)
  • 3 개, 4 개 또는 n- 웨이 분할과 같이 2 개 이상의 분할을 지원합니다.

프로그램이 대소 문자 입력을 지원해야합니까? 그렇다면 출력의 경우를 버릴 수 있습니까?
Nemo157

@ Nemo157 대소 문자를 무시할 수 있으며 출력에서 ​​보존하지 않아도됩니다.
Thomas O

요청 된 출력 부분이 사람에게 분명하다면 프로그램이 추가 자료를 출력 할 수 있습니까?
JB

@JB 그렇습니다.
Thomas O

좋아, 나는 그 펄을 향상시킬 것이다.;) 감사
JB

답변:


4

펄 115 118 123

@_=~/./g;for$i(1..1<<@_){$l=$
r;$i&1<<$_?$l:$r+=64-ord$_[$_
]for 0..$#_;$l-$r||$i&1<<$_&&
print$_[$_]for 0..$#_;say""}

로 실행하십시오 perl -nE '<code goes here>'. 그 'n'은 코드 크기로 계산됩니다.

이격 :

@_ = /./g;
for $i (1 .. 1<<@_) {
  $l = $r;
  $i & 1<<$_ ? $l : $r -= 64 - ord $_[$_] for 0 .. $#_;

  $l - $r      ||
  $i & 1<<$_   &&
  print $_[$_]
    for 0 .. $#_;

  say ""
}

주석과 변수 이름으로 :

# split a line of input by character
@chars = /./g;

# generate all binary masks of same length
for $mask (1 .. 1<<@_) {

  # start at "zero"
  $left_sum = $right_sum;

  # depending on mask, choose left or right count
  # 1 -> char goes left; 0 -> char goes right
  $mask & 1<<$_ ? $left_sum : $right_sum
    -= 64 - ord $chars[$_]   # add letter value
      for 0 .. $#chars;      # for all bits in mask

  # if left = right
  $left_sum - $right_sum ||

  # if character was counted left (mask[i] = 1)
  $mask & 1<<$_          &&

  # print it
  print $chars[$_]

  # ...iterating on all bits in mask
    for 0 .. $#chars;

  # newline
  say ""
}

사용 된 몇 가지 트릭 :

  • 1..1<<@_와 같은 비트 범위를 포함 0..(1<<@_)-1하지만 더 짧습니다. (범위 경계를 여러 번 포함하여 멀리 떨어진 곳에서 문제를 고려해도 출력이 잘못되지는 않습니다.)
  • $ left_range와 $ right_range는 실제 "0"숫자 0으로 리셋되지 않습니다 : 우리는 결국 그것들을 모아서 비교하기 때문에, 같은 값에서 시작하기 만하면됩니다.
  • 덧셈 64-ord$_[$_]대신 뺄셈 ord$_[$_]-64은 보이지 않는 문자를 얻는다 : 구분자로 끝나기 때문에 for불필요한 공간을 만든다 .
  • 펄은 삼항 조건 연산자에 의해 결정된 변수에 할당 할 수 있습니다 : cond ? var1 : var2 = new_value.
  • 부울 표현과 체인 &&||대신 적절한 조건문으로 사용된다.
  • $l-$r 보다 짧다 $l!=$r
  • 균형이 맞지 않는 스플릿에서도 줄 바꿈을 출력합니다. 빈 줄은 규칙에 따라 괜찮습니다! 나는 물었다!

라인 노이즈를 사용하지 않는 사람들을 위해 설명해 주시겠습니까? 내 것과 비슷한 이진 마스크 ​​접근 방식을 사용하는 것처럼 보이며 64는 '@'= 'A'-1을 의미하며 그 후 거의 잃어 버렸습니다.
dmckee --- 전 운영자 고양이 1

이 편집이 더 좋습니까?
JB

좋은. 왼쪽 또는 오른쪽 합계에 각 카운트 추가를 활용하는 것에 대해 생각해야합니다. 분명 했어야했지만 놓쳤다.
dmckee --- 전 운영자 고양이

3

J (109)

~.(/:{[)@:{&a.@(96&+)&.>>(>@(=/@:(+/"1&>)&.>)#[),}.@(split~&.>i.@#@>)@<@(96-~a.&i.)"1([{~(i.@!A.i.)@#)1!:1[1

에 대한 출력 wordsplit:

┌─────┬─────┐
│ 로우 │ 디프 스트 │
├─────┼─────┤
│ 딜트 │ 오퍼 │
├─────┼─────┤
│iptw │ 극장 │
├─────┼─────┤
│ 문구 │iptw │
├─────┼─────┤
│ 오퍼 │ 딜트 │
├─────┼─────┤
│ 딥 │ 로워 │
└─────┴─────┘

설명:

  • 1!:1[1: stdin에서 줄을 읽습니다.
  • ([{~(i.@!A.i.)@#): 모든 순열을 얻는다
  • "1: 각 순열에 대해 :
  • (96-~a.&i.): 문자 점수 받기
  • }.@(split~&.>i.@#@>)@<: 첫 번째 숫자 앞과 마지막 숫자를 제외하고 가능한 각 공간에서 점수의 각 순열을 나눕니다.
  • >(>@(=/@:(+/"1&>)&.>)#[): 반이 일치하는 순열을 확인하고 다음을 선택하십시오.
  • {&a.@(96&+)&.>: 점수를 문자로 다시 설정
  • ~.(/:{[): 사소한 변형 제거 (예 : ordsl wpitordsl wpti)

귀하의 답변 중 일부가 중복되었습니다.
DavidC

@DavidCarraher : 글쎄요, 저는 장님이거나이 사람이 아니거나 최근 답변이 아닙니다. 나는 의도적으로 다른 사람들의 대답을 복사하지 않았습니다. 물론 당신이 옳을 수도 있지만, 가끔 술에 취해 게시했으며 많은 공감대를 얻을 때까지 기억하지 못했습니다. 수정에 가깝다. 내가 잘못 행동 한 것을 본 적이 있다면, 내가 잘못 행동하고있는 의견을 남길 수 있습니다. 또는 다운 보트가 원하는대로 다운 보트 할 수도 있습니다.
marinus

조금도 의도되지 않았습니다. 예를 들어 첫 번째 답변 { "lorw", "dipst"}은 최종 답변 { "dipst", "lorw"}과 중복됩니다. 단어의 순서 만 다릅니다.
DavidC

@DavidCarraher : whoops : PI는 누군가의 답변을 복사하겠다고 생각했다 ... 어쨌든이 질문은 (올바르게 해석하면) 개별 부분이 서로 순열이지만 중복되지 않는 중복 부분을 제거하기 위해 말합니다. 부품의 순서가 다른 것, 즉 {a,bc}이미 발견 된 경우 제거 {a,cb}하지만 제거 하지 않는 것 {bc,a}. (물론 나는 누군가의 대답을 실제로 / 가지고 / 복제했다면 누군가가 그것을 지적하면 그것을 선호합니다.)
marinus

당신이 옳은 것 같습니다. 지시 사항에 따르면 단어 순서를 무시해도되지만 ( "각 문자 그룹마다 하나씩 만 나열하면됩니다"), 필요하지는 않습니다. 이렇게하면 몇자를 구할 수 있습니다. 감사.
DavidC

2

c99-379 필요한 문자

#include <stdio.h>
#include <string.h>
#include <ctype.h>
int s(char*w,int l,int m){int b,t=0;for(b=0;b<l;++b){t+=(m&1<<b)?toupper(w[b])-64:0;}return t;}
void p(char*w,int l,int m){for(int b=0;b<l;++b){putchar((m&1<<b)?w[b]:32);}}
int main(){char w[99];gets(w);int i,l=strlen(w),m=(1<<l),t=s(w,l,m-1);
for(i=0;i<m;i++){if(s(w,l,i)==t/2){p(w,l,i);putchar(9);p(w,l,~i);putchar(10);}}}

접근 방식은 매우 분명합니다. 마스크에 따라 단어를 합산하는 기능과 마스크에 따라 인쇄하는 기능이 있습니다. 표준 입력에서 입력. 한 가지 이상한 점은 인쇄 루틴이 마스크에없는 문자를위한 공백을 삽입한다는 것입니다. 탭은 그룹을 분리하는 데 사용됩니다.

나는 보너스 아이템들 중 어느 것도하지 않으며 그것들을 지원하기 위해 쉽게 변환되지도 않는다.

읽고 주석을 달았습니다 :

#include <stdio.h>
#include <string.h>
#include <ctype.h>
int s(char *w, int l, int m){ /* word, length, mask */
  int b,t=0;                  /* bit and total */
  for (b=0; b<l; ++b){        
/*     printf("Summing %d %d %c %d\n",b,m&(1<<b),w[b],toupper(w[b])-'A'-1); */
    t+=(m&1<<b)?toupper(w[b])-64:0; /* Add to toal if masked (A-1 = @ = 64) */
  }
  return t;
}
void p(char *w, int l, int m){
  for (int b=0; b<l; ++b){ 
    putchar((m&1<<b)?w[b]:32);  /* print if masked (space = 32) */
  }
}
int main(){
  char w[99];
  gets(w);
  int i,l=strlen(w),m=(1<<l),t=s(w,l,m-1);
/*   printf("Word is '%s'\n",w); */
/*   printf("...length %d\n",l); */
/*   printf("...mask   0x%x\n",m-1); */
/*   printf("...total  %d\n",t); */
  for (i=0; i<m; i++){
/*     printf("testing with mask 0x%x...\n",i); */
    if (s(w,l,i)==t/2) {p(w,l,i); putchar(9); p(w,l,~i); putchar(10);}
    /* (tab = 9; newline = 10) */
  }
}

확인

 $ wc wordsplit_golf.c
  7  24 385 wordsplit_golf.c
 $ gcc -std=c99 wordsplit_golf.c
 $ echo wordsplit | ./a.out
warning: this program uses gets(), which is unsafe.
 or sp          w  d  lit
wor   l            dsp it
 ords l         w    p it
w    p it        ords l  
   dsp it       wor   l  
w  d  lit        or sp   

1

루비 : 125 자

r=->a{a.reduce(0){|t,c|t+=c.ord-96}}
f=r[w=gets.chomp.chars]
w.size.times{|n|w.combination(n).map{|s|p([s,w-s])if r[s]*2==f}}

샘플 실행 :

bash-4.2$ ruby -e 'r=->a{a.reduce(0){|t,c|t+=c.ord-96}};f=r[w=gets.chomp.chars.to_a];w.size.times{|p|w.combination(p).map{|q|p([q,w-q])if r[q]*2==f}}' <<< 'wordsplit'
[["w", "o", "r", "l"], ["d", "s", "p", "i", "t"]]
[["w", "p", "i", "t"], ["o", "r", "d", "s", "l"]]
[["o", "r", "s", "p"], ["w", "d", "l", "i", "t"]]
[["w", "d", "l", "i", "t"], ["o", "r", "s", "p"]]
[["o", "r", "d", "s", "l"], ["w", "p", "i", "t"]]
[["d", "s", "p", "i", "t"], ["w", "o", "r", "l"]]

1

매스 매 티카 123 111

단어의 "ascii total"이 1/2 인 단어의 모든 하위 집합을 찾습니다 d. 그런 다음 해당 하위 집합의 보완을 찾습니다.

d = "WORDSPLIT"

{#, Complement[w, #]}&/@Cases[Subsets@#,x_/;Tr@x==Tr@#/2]&[Sort[ToCharacterCode@d - 64]];
FromCharacterCode[# + 64] & /@ %

{{ "IPTW", "DLORS"}, { "LORW", "DIPST"}, { "OPRS", "DILTW"}, { "DILTW", "OPRS"}, { "DIPST", "LORW"} , { "DLORS", "IPTW"}}


1

J, 66 자

base2 숫자의 숫자를 사용하여 가능한 모든 서브 세트를 선택하십시오.

   f=.3 :'(;~y&-.)"{y#~a#~(=|.)+/"1((+32*0&>)96-~a.i.y)#~a=.#:i.2^#y'
   f 'WordSplit'
┌─────┬─────┐
│Worl │dSpit│
├─────┼─────┤
│Wdlit│orSp │
├─────┼─────┤
│Wpit │ordSl│
├─────┼─────┤
│ordSl│Wpit │
├─────┼─────┤
│orSp │Wdlit│
├─────┼─────┤
│dSpit│Worl │
└─────┴─────┘

0

내 솔루션은 다음과 같습니다. 크기가 거의 반 골프이지만 매우 잘 작동합니다. n-way split을 지원하고 (약 3 개의 split 이상의 계산 시간이 매우 길어 지지만) 중복 제거를 지원합니다.

class WordSplitChecker(object):
    def __init__(self, word, splits=2):
        if len(word) == 0:
            raise ValueError, "word too short!"
        if splits == 0:
            raise ValueError, "splits must be > 1; it is impossible to split a word into zero groups"
        self.word = word
        self.splits = splits

    def solve(self, uniq_solutions=False, progress_notifier=True):
        """To solve this problem, we first need to consider all the possible
        rearrangements of a string into two (or more) groups.

        It turns out that this reduces simply to a base-N counting algorithm,
        each digit coding for which group the letter goes into. Obviously
        the longer the word the more digits needed to count up to, so 
        computation time is very long for larger bases and longer words. It 
        could be sped up by using a precalculated array of numbers in the
        required base, but this requires more memory. (Space-time tradeoff.)

        A progress notifier may be set. If True, the default notifier is used,
        if None, no notifier is used, and if it points to another callable,
        that is used. The callable must take the arguments as (n, count, 
        solutions) where n is the number of iterations, count is the total 
        iteration count and solutions is the length of the solutions list. The
        progress notifier is called at the beginning, on every 1000th iteration, 
        and at the end.

        Returns a list of possible splits. If there are no solutions, returns
        an empty list. Duplicate solutions are removed if the uniq_solutions
        parameter is True."""
        if progress_notifier == True:
           progress_notifier = self.progress 
        solutions = []
        bucket = [0] * len(self.word)
        base_tuple = (self.splits,) * len(self.word)
        # The number of counts we need to do is given by: S^N,
        # where S = number of splits,
        #       N = length of word.
        counts = pow(self.splits, len(self.word))
        # xrange does not create a list in memory, so this will work with very
        # little additional memory.
        for i in xrange(counts):
            groups = self.split_word(self.word, self.splits, bucket)
            group_sums = map(self.score_string, groups)
            if len(set(group_sums)) == 1:
                solutions.append(tuple(groups))
            if callable(progress_notifier) and i % 1000 == 0:
                progress_notifier(i, counts, len(solutions))
            # Increment bucket after doing each group; we want to include the
            # null set (all zeroes.)
            bucket = self.bucket_counter(bucket, base_tuple)
        progress_notifier(i, counts, len(solutions))
        # Now we have computed our results we need to remove the results that
        # are symmetrical if uniq_solutions is True.
        if uniq_solutions:
            uniques = []
            # Sort each of the solutions and turn them into tuples.  Then we can 
            # remove duplicates because they will all be in the same order.
            for sol in solutions:
                uniques.append(tuple(sorted(sol)))
            # Use sets to unique the solutions quickly instead of using our
            # own algorithm.
            uniques = list(set(uniques))
            return sorted(uniques)
        return sorted(solutions)

    def split_word(self, word, splits, bucket):
        """Split the word into groups. The digits in the bucket code for the
        groups in which each character goes in to. For example,

        LIONHEAD with a base of 2 and bucket of 00110100 gives two groups, 
        "LIHAD" and "ONE"."""
        groups = [""] * splits
        for n in range(len(word)):
            groups[bucket[n]] += word[n]
        return groups

    def score_string(self, st):
        """Score and sum the letters in the string, A = 1, B = 2, ... Z = 26."""
        return sum(map(lambda x: ord(x) - 64, st.upper()))

    def bucket_counter(self, bucket, carry):
        """Simple bucket counting. Ex.: When passed a tuple (512, 512, 512)
        and a list [0, 0, 0] it increments each column in the list until
        it overflows, carrying the result over to the next column. This could
        be done with fancy bit shifting, but that wouldn't work with very
        large numbers. This should be fine up to huge numbers. Returns a new
        bucket and assigns the result to the passed list. Similar to most
        counting systems the MSB is on the right, however this is an 
        implementation detail and may change in the future.

        Effectively, for a carry tuple of identical values, this implements a 
        base-N numeral system, where N+1 is the value in the tuple."""
        if len(bucket) != len(carry):
            raise ValueError("bucket and carry lists must be the same size")
        # Increase the last column.
        bucket[-1] += 1 
        # Carry numbers. Carry must be propagated by at least the size of the
        # carry list.
        for i in range(len(carry)):
            for coln, col in enumerate(bucket[:]):
                if col >= carry[coln]:
                    # Reset this column, carry the result over to the next.
                    bucket[coln] = 0
                    bucket[coln - 1] += 1
        return bucket

    def progress(self, n, counts, solutions):
        """Display the progress of the solve operation."""
        print "%d / %d (%.2f%%): %d solutions (non-unique)" % (n + 1, counts, (float(n + 1) / counts) * 100, solutions) 

if __name__ == '__main__':
    word = raw_input('Enter word: ')
    groups = int(raw_input('Enter number of required groups: '))
    unique = raw_input('Unique results only? (enter Y or N): ').upper()
    if unique == 'Y':
        unique = True
    else:
        unique = False
    # Start solving.
    print "Start solving"
    ws = WordSplitChecker(word, groups)
    solutions = ws.solve(unique)
    if len(solutions) == 0:
        print "No solutions could be found."
    for solution in solutions:
        for group in solution:
            print group,
        print

샘플 출력 :

Enter word: wordsplit
Enter number of required groups: 2
Unique results only? (enter Y or N): y
Start solving
1 / 512 (0.20%): 0 solutions (non-unique)
512 / 512 (100.00%): 6 solutions (non-unique)
dspit worl
ordsl wpit
orsp wdlit

1
제 생각에 원문의 목표 (코드 간결성)를 충족시키려는 시도가 전혀 없다는 답변은 사실상 논제입니다. 이 답변은 코드 골프와 관련이 없으므로 답변으로 게시하는 것이 아니라 다른 곳에 게시하고 질문에 대한 의견에 링크를 연결하는 것이 좋습니다.
Jeff Swensen

2
@Sugerman : 게임을이기려는 시도가 아니라 참조 구현입니다. 페이지 상단의 공간을 차지하는 대신 참조 구현을 답변으로 선호하며 링크 썩음의 위험을 제거하기 위해 현장에서 선호합니다.
dmckee --- 전 운영자 고양이

@Sugerman : 제출하지 않으시겠습니까? 아무것도 아닌 것보다 낫습니다. 그것은 최소화, 그런데 왜 귀찮게 할 수 - 난 정말 내 자신의 질문을 받아 들일 수 없다 (물론, 내가 할 수 있지만, 그것의 정신이 아니다.)
토마스 O

그것의 기초에, 이것은 질문 및 답변 사이트입니다. 답변이 아닌 내용을 게시해서는 안됩니다.
Jeff Swensen

1
첫 번째 의견에서 말했듯이, 질문에 대한 의견에서 또는 귀하가 질문을 소유하고 있으므로 링크를 편집하십시오. 다른 모든 사항 (및 투표 결과)을 고려하지 않고 자신의 답변을 자동으로 수락하지 않는 한 자신의 질문에 답변을 제출해도 아무런 문제가 없습니다.
Jeff Swensen

0

루아-195

a=io.read"*l"for i=0,2^#a/2-1 do z,l=0,""r=l for j=1,#a do b=math.floor(i/2^j*2)%2 z=(b*2-1)*(a:byte(j)-64)+z if b>0 then r=r..a:sub(j,j)else l=l..a:sub(j,j)end end if z==0 then print(l,r)end end

입력은 대문자 여야합니다.

~$ lua wordsplit.lua 
>WORDSPLIT
WDLIT   ORSP
DSPIT   WORL
WPIT    ORDSL

0

파이썬-127

w=rawinput()
for q in range(2**len(w)/2):
 a=[0]*2;b=['']*2
 for c in w:a[q%2]+=ord(c)-96;b[q%2]+=c;q/=2
 if a[0]==a[1]:print b

그리고 여기에 중복없이 182 바이트의 n 분할 버전이 있습니다.

n,w=input()
def b(q):
 a=[0]*n;b=['']*n
 for c in w:a[q%n]+=ord(c)-96;b[q%n]+=c;q/=n
 return a[0]==a[1] and all(b) and frozenset(b)
print set(filter(None,map(b,range(n**len(w)/n))))

입력은 다음과 같습니다.

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