코드 너겟


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

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

다른 잘못된 출력도 있습니다. 제가 잘못 본게 아니라면, 당신의 순서를 교환하여 그들 모두를 해결할 수 9및 10.
— 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 9인 10 초, 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 -> j ∈ packs, 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.