코드 너겟


18

코드 너겟

그것은의 그것이 가상의 상황 금요일 저녁, 당신은 당신의 마음에 드는 취미에 참여하는 일반 골프를 치는 친구를 통해 초대했습니다 : 코드 골프. 그러나 이것은 두뇌 유출 작업이므로 그룹에서 두뇌 음식을 선택해야 코드에서 최대한 많은 골프를 즐길 수 있습니다.

이제 모든 사람이 가장 좋아하는 간식은 치킨 너겟이지만 문제가 있습니다. 모든 사람의 요구를 충족시키는 단일 팩은 없습니다. 따라서 이미 골프 분위기에 빠졌으므로 모든 사람의 너겟 요구를 충족시키기 위해 구매해야 할 팩을 정확히 파악하는 프로그램을 만들기로 결정했습니다.

치킨 너겟 팩 크기는 어디에나 있으며, 세계에서 거주하는 지역에 따라 표준 크기도 변경됩니다. 그러나 가장 가까운 [너겟을 제공하는 장소] 에는 다음과 같은 크기의 너겟 팩이 있습니다.

4, 6, 9, 10, 20, 40

이제 너겟의 특정 조합을 주문할 수 없다는 것을 알 수 있습니다. 예를 들어, 정확히 11같은 조합이 없기 때문에 너겟은 불가능합니다 11. 그러나 431 팩 20, 1 팩 10, 1 팩 9및 1 팩을 얻어서 만들 수 있습니다 4.

20 + 10 + 9 + 4 = 43 (597)

여기서 597각 항은 제곱되고 함께 더해집니다 (힌트 : 최적 솔루션의 값이 가장 높음) . 물론 다른 방법도 43있지만, 아시다시피, 팩당 너겟이 많을수록 너겟 당 저렴합니다. 따라서 비용을 최소화하기 위해 가장 적은 수의 팩을 대량으로 구매하는 것이 이상적입니다.

작업

각 개인의 요구 사항에 해당하는 정수 목록을 취하는 프로그램 이나 함수 를 만들어야합니다 . 그런 다음 치킨 너겟을 구매하기 위해 가장 비용 효율적인 α 주문을 계산하고 인쇄 해야합니다 . 가장 비용 효율적인 α 차수는 각 수량의 제곱의 합이 가장 높은 조합입니다. 완벽하게 너겟을 살 수있는 방법이 전혀 존재하지 않는 경우, 당신은해야한다 인쇄 와 같은 falsy 값을 , , , 또는 언어로 볼 수 있습니다 뭐든간에.0FalseImpossible!

예제 I / O :

[2 7 12 4 15 3] => [20 10 9 4]
     1, 1, 2, 1 => False
  6 5 5 5 5 5 9 => 40
      [6, 4, 9] => 9 10
              1 => 0
            199 => 40, 40, 40, 40, 20, 10, 9
              2 => Impossible!

여기 에 처음 400에 대한 이상적인 솔루션의 목록이 있습니다. 이것들은 여러분이 기대하는 방식으로 형식화되지 않았으며 각각 tuple은 형식 (N lots of M)입니다.

규칙

  1. 표준 허점이 없습니다.
  2. FrobeniusSolveMathematica 와 같이 작업의 전부 또는 대부분을 수행하는 내장 함수를 사용하지 마십시오 .

α-예를 들어 이것을 명확히하기 위해을 수행하여 43을 만들 수도 4 + 6 + 6 + 9 + 9 + 9 = 43 (319)있지만, 제곱의 합이 소개에서 언급 한 조합보다 작으므로 최적이 아니므로 잘못된 출력입니다. 본질적으로, 더 높은 제곱합 = 더 낮은 비용 = 가장 비용 효율적인.


시간 / 메모리 제한이 있습니까?
Dennis

@Dennis 시간이나 메모리 제한이 없습니다.
Kade

4
실제로 목요일입니다.
mbomb007

4
@ mbomb007 Astute 관찰 : P 소개를 조정했습니다.
Kade

2
나는 치킨 맥 너겟 정리를 어떻게 든 사용해야한다 ...
Stretch Maniac

답변:


7

Pyth, 26 25 바이트

e+Zo.aNf!-TCM"  
("./sQ

인쇄 할 수없는 문자가 있습니다. 온라인으로 시연하십시오 . 꽤 느립니다 (그러나 26 바이트 솔루션만큼 느리지는 않습니다).

설명:

                          implicit: Q = input list
                     sQ   sum(Q)
                   ./     generate all integer partitions
       f                  filter for partitions T, which satisfy:
             "   ("          string containing chars with the ASCII-values of 4,6,9,10,20,40
           CM                convert each char to the ASCII-value
         -T                  remove this numbers from T
        !                    and check, if the resulting list is empty
    o                      order the remaining subsets N by:
     .aN                      the vector length of N (sqrt of sum of squares)
  +Z                       insert 0 at the beginning
 e                         print the last element

Pyth, 32 바이트

e+Zo.aNfqsTsQysm*]d/sQdCM"  
(

인쇄 할 수없는 문자가 있습니다. 온라인으로 사용해보십시오 : 데모이 버전은 더 빠릅니다. [6,7,8]약 1 [30]초 안에 입력 솔루션과 약 90 초 안에 입력 솔루션을 찾습니다 .

설명:

                                 implicit: Q = input list
                          "...(  the string containing chars with the ASCII-values of 4,6,9,10,20,40
                        CM       convert each char to the ASCII-value
                m                map each number d to:
                  ]d                create the list [d]
                 *  /sQd            and repeat it sum(Q)/d times
               s                 unfold
              y                  generate all subsets
        f                        filter for subsets T, which satisfy:
         qsTsQ                      sum(Q) == sum(T)
    o                            order the remaining subsets N by:
     .aN                            the vector length of N (sqrt of sum of squares)
  +Z                             insert 0 at the beginning
 e                               print the last element

왜 합이 아닌 제곱합의 sqrt로 표시됩니까?
mbomb007

1
@ mbomb007 중요하지 않기 때문에. a> b 인 경우 sqrt (a)> sqrt (b)보다 크거나 같지 않습니다. 그리고 .a방법을 사용하는 것은 제곱과 합산보다 짧습니다 s^R2.
Jakube

5

175 153

sub f{my$n=$_[0];if(!$n){return 1;}foreach$o(40,20,9,10,6,4){if($n>=$o&&f($n-$o)){print"$o ";return 1;}}return 0;}$n+=$_ for@ARGV;if(!f($n)){print":(";}

프로그램 인수에서 입력을받습니다. 완벽한 해결책을 찾지 못하면 :()를 인쇄합니다 .

Ungolfed Code :

sub f
{
    my $n = $_[0];
    if(!$n)
    {
        return 1;
    }
    foreach $o(40,20,9,10,6,4)
    {
        if($n>=$o&&f($n-$o))
        {
            print "$o ";
            return 1;
        }
    }
    return 0;
}

$n += $_ for @ARGV;
if(!f($n))
{
    print ":(";
}

추신 : 이것은 아마도 10 분이 걸리지 않은 첫 번째 항목 일 것입니다 1 2.)

여기서 확인하십시오.


지금까지 가장 빠른 프로그램 인 것으로 축하합니다! 내 참조 프로그램보다 빠를 수도 있습니다 : P 사람들이 출력을 볼 수 있도록 게시물 맨 아래에 ideone 링크를 추가했습니다.
Kade

코드가 잘못된 출력을 생성 할 수 있습니다. 입력 189 9아닌, 인쇄되어야합니다 4 4 10.
Dennis

다른 잘못된 출력도 있습니다. 제가 잘못 본게 아니라면, 당신의 순서를 교환하여 그들 모두를 해결할 수 910.
Dennis

@ 데니스 감사합니다.
토마스 올트 만

3

CJam, 45 29 28 바이트

q~:+_[40K9A6Z)U]m*_::+@#=0-p

이 방법은 매우 느리고 메모리를 많이 사용합니다.

CJam 통역사 에서 온라인으로 사용해보십시오 .

5 바이트의 비용으로 크게 속도를 높일 수 있습니다.

q~:+_40/4+[40K9A6Z)U]m*_::+@#=0-p

입력의 합으로는 복잡성이 여전히 기하 급수적이지만 온라인 인터프리터에서는 최대 159 개, Java 인터프리터에서는 최대 199 개의 테스트 사례를 몇 초 안에 처리해야합니다.

CJam 통역사 에서 온라인으로 사용해보십시오 .

생각

최적 구매 (사각형의 최대 합) 많은로서 갖는 유효한 구매 (너겟의 정확한 개수)는 40 '많은 것에 따라 가능한이야 20 '가능한 s가 다음 몇으로 9 '(예 가능한이야 9 910 초, 6 초 및 4 초에 10 4 4대해) 등이 바람직하다 .

이 접근법에서, 우리 는 배열 의 N 개 사본의 카티 전 곱을 생성합니다 [40 20 9 10 6 4 0] . 여기서 N 은 원하는 너겟 수입니다. N 은 우리가해야하는 구매 횟수의 상한입니다. 코드의 속도 향상 버전에서는 N / 40 + 4를 대신 사용합니다.

배열의 순서에 따라 카티 전 곱은 벡터 [40 ... 40]으로 시작 하여 벡터 [0 ... 0]로 끝납니다 . 올바른 합 (최적의 제곱합을 가짐)이있는 첫 번째 벡터의 인덱스를 계산하고 해당 배열 요소를 검색하고 자리 표시 자로 사용 된 0을 제거하고 결과를 인쇄합니다.

벡터를 찾을 수 없으면 인덱스는 -1이 되고 [0 ... 0]을 검색 하여 대신 빈 배열을 인쇄합니다.

암호

q~                            e# Read from STDIN and evaluate the input.
  :+                          e# Push N, the sum of all elements of the resulting array.
     [40K9A6Z)U]              e# Push B := [40 20 9 10 6 4 0].
    _           m*            e# Push B**N, the array of all vectors of dimension N
                              e# and coordinates in B.
                  _::+        e# Copy and replace each vector by its sum.
                      @#      e# Get the first index of N.
                        =     e# Retrieve the corresponding element.
                         0-p  e# Remove 0's and print.

이 :)에 관계없이 빠른 코드 마무리를시키는 것보다 것이다 손으로 솔루션에서 작동하는 몇 가지 상황 중 하나 .. 좋은 일이 될 수 있습니다
카데

2

줄리아, 126 바이트

r->(t=filter(i->all(j->j[4,6,9,10,20,40],i),partitions(sum(r)));show(!isempty(t)&&collect(t)[indmax(map(k->sum(k.^2),t))]))

이것은 솔루션이 존재하는지 여부에 따라 배열을 입력으로 받아들이고 STDOUT에 배열 또는 부울을 인쇄하는 이름없는 함수를 작성합니다. 호출하려면 이름을 지정하십시오 (예 :) f=n->....

언 골프 + 설명 :

function f(r)
    # Nugget pack sizes
    packs = [4, 6, 9, 10, 20, 40]

    # Filter the set of arrays which sum to the required number of nuggets
    # to those for which each element is a nugget pack
    t = filter(i -> all(j -> jpacks, i), partitions(sum(r)))

    # Print the boolean false if t is empty, otherwise print the array of
    # necessary nugget packs for which the sum of squares is maximal
    show(!isempty(t) && collect(t)[indmax(map(k -> sum(k.^2), t))])
end

예 :

julia> f([1])
false

julia> f([2,7,12,4,15,3])
[20,10,9,4]

1

파이썬 3-265 자

import itertools as i
n=list(map(int,input().split(',')));m=[]
for f in range(1,9):
 for j in range(6*f):
  for x in i.combinations((4,6,9,10,20,40,)*f,j+1):
   if sum(n)==sum(x):m.append(x)
if m!=[]:v=[sum(l**2for l in q)for q in m];print(m[v.index(max(v))])
else:print(0)

간격 표시 :

import itertools as i
n=list(map(int,input().split(',')));m=[]
for f in range(1,5):
 for j in range(6*f):
\tfor x in i.combinations((4,6,9,10,20,40,)*f,j+1):
\t if sum(n)==sum(x):m.append(x)
\t\tif m!=[]:v=[sum(l**2for l in q)for q in m];print(m[v.index(max(v))])
else:print(0)

모든 테스트 사례를 통과

참고 : 너무 느리기 때문에이 모든 경우를 통과 할 경우 몰라요 ...하지만 해야 ...


지금이 문제가 아무것도 보이지 않습니다. 테스트하고 볼 것입니다. 집에 도착하면 Gist에있는 목록을 생성하는 데 사용되는 참조되지 않은 참조 프로그램을 추가합니다. 나는 타이밍이 아니었지만 모든 경우에 8-12 분 범위에 어딘가에 걸렸다 고 생각합니다.
Kade

@ Vioz- 브릴리언트! : D
Beta Decay

36을 테스트 한 후 MemoryError가 발생하기 전에 약 4 천만 개의 조합 (정확하게는 40,007,602)을 통과합니다. 4GB의 메모리 만 있기 때문에 이것은 내 작업 기계의 제한 사항 일 수 있습니다.
Kade

@ Vioz- 흠 ... 글쎄, 내가 휴대 전화에서 테스트를 수행하는 것은 희망이 없다 ...
Beta Decay

1
@undergroundmonorail 한 번만 사용하는 경우 <= 4자인 경우 곧바로 가져 오는 것이 좋습니다 (5 나누기). 그러나 두 번 이상 사용하면 from blah import*항상 가장 좋습니다. 위의 내용을 생각할 수있는 유일한 예외는 여러 개가있는 경우 입니다. 실제로 유용한 import곳을 염두에 두는 유일한 시간입니다 as.
Sp3000

1

자바 스크립트, 261 256 261

d="length";function g(a){for(z=y=0;y<a[d];z+=+a[y++]);return z}x=[40,20,10,9,6,4];l=prompt().split(",");o=g(l);p=[];for(i=0;i<x[d];i++)r=g(p),s=r+x[i],(s<o-3||s==o)&&p.push(x[i]),(i==x[d]-1||40<o-r)&&r+x[i]<o-3&&(i=-1,0==i||o-r<p[p[d]-1]&&p.pop());g(p)==o&&p||0

이것이 괜찮은지 잘 모르겠습니다. 작동하는 것 같지만 반드시 누락되었습니다.

느리게 보이지는 않지만 거의 즉시 123456출력 [40 x 3086, 10, 6]됩니다.

설명:

너겟 크기 반복 (가장 큰 것부터)

  • 스택과 너깃 크기의 합이 목표보다 작 으면-3-> 스택에 밀어 넣으십시오.
  • 40 개가 남은 경우-> 루프 카운터를 재설정하십시오
  • 마지막 너깃 크기에 도달했을 때 스택의 합이 목표보다 큰 경우-> 마지막 요소를 팝하면 루프 카운터를 재설정하십시오.
  • 스택의 합이 합산되면 반환하고, 그렇지 않으면 0을 반환

199 년 | 1 쌓인 스택은 다음과 같습니다

i | stack
0   [40]
0   [40, 40]
0   [40, 40, 40]
0   [40, 40, 40, 40]
0   [40, 40, 40, 40]
1   [40, 40, 40, 40, 20]
2   [40, 40, 40, 40, 20, 10]
3   [40, 40, 40, 40, 20, 10, 9]
4   [40, 40, 40, 40, 20, 10, 9]
5   [40, 40, 40, 40, 20, 10, 9]
==> [40, 40, 40, 40, 20, 10, 9]

1

i | stack
0   []
1   []
2   []
3   []
4   []
5   []
==> 0

1
당신의 접근 방식은 목표에 도달 할 수 있는지 확인하지 않는 것 같습니다. 11인쇄 [6]18인쇄 [10, 4].
Dennis

@Dennis 안녕하세요, 지적 해 주셔서 감사합니다. 어제 늦은 밤이었습니다. 5 자로 수정했습니다. 18 [10,4]쌍의 괄호가 없어서 인쇄 되었습니다. 확인은 실제로 잘못되었습니다. 결과 집합에 하나 이상의 요소가 있는지 확인했지만 올바르게 요약되지는 않았습니다. 내가 무슨 생각을했는지 모르겠다
C5H8NNaO4
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.