Mã cố định


18

Mã cố định

Đó là một tình huống giả định vào tối thứ Sáu và bạn đã mời những người bạn chơi golf thông thường tham gia vào sở thích yêu thích của bạn: chơi golf mã. Tuy nhiên, vì đây là một nhiệm vụ làm cạn kiệt não bộ, bạn cần chọn một số thực phẩm bổ não cho nhóm để bạn có thể chơi golf nhiều nhất có thể khỏi mã của mình.

Bây giờ, món ăn vặt yêu thích của mọi người là cốm gà, nhưng có một vấn đề: Không có gói duy nhất nào đáp ứng nhu cầu của mọi người. Vì vậy, vì bạn đã có tâm trạng chơi gôn, bạn quyết định tạo một chương trình tìm ra chính xác những gói bạn phải mua để có thể đáp ứng nhu cầu Nugget của mọi người.

Kích cỡ gói nugget gà ở khắp mọi nơi, và tùy thuộc vào nơi bạn sống trên thế giới, kích thước tiêu chuẩn cũng thay đổi. Tuy nhiên, [nơi phục vụ cốm] gần nhất có các kích cỡ sau của gói nugget:

4, 6, 9, 10, 20, 40

Bây giờ bạn có thể nhận thấy rằng bạn không thể đặt hàng các kết hợp cố định nhất định. Ví dụ, 11cốm là không thể, vì không có sự kết hợp nào 11chính xác bằng nhau . Tuy nhiên, bạn có thể thực hiện 43bằng cách nhận 1 gói 20, 1 gói 10, 1 gói 9và 1 gói 4,

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

trong đó 597mỗi thuật ngữ bình phương và được cộng lại với nhau (gợi ý: giải pháp tối ưu có giá trị này là giá trị cao nhất) . Tất nhiên có nhiều cách khác để làm 43, nhưng như bạn biết, càng nhiều cốm trên mỗi gói, giá càng rẻ cho mỗi nugget. Vì vậy, bạn muốn lý tưởng mua số lượng gói ít nhất và với số lượng lớn nhất để giảm thiểu chi phí của bạn.

Nhiệm vụ

Bạn nên tạo một chương trình hoặc hàm có danh sách các số nguyên tương ứng với yêu cầu của mỗi người. Sau đó, bạn nên tính toán và in thứ tự α hiệu quả nhất để mua cốm gà. Thứ tự α hiệu quả nhất về chi phí là sự kết hợp theo đó tổng bình phương của mỗi đại lượng là cao nhất. Nếu có hoàn toàn không có cách nào để mua cốm một cách hoàn hảo, bạn phải in một giá trị falsy như 0, False, Impossible!, hoặc bất cứ điều gì có sẵn trong ngôn ngữ của bạn.

Ví dụ 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!

Dưới đây là danh sách các giải pháp lý tưởng cho 400 đầu tiên. Lưu ý những giải pháp này không được định dạng theo cách tôi mong đợi là của bạn, mỗi giải pháp đều tupleở dạng (N lots of M).

Quy tắc

  1. Không có sơ hở tiêu chuẩn.
  2. Không sử dụng các hàm dựng sẵn thực hiện tất cả hoặc phần lớn nhiệm vụ, chẳng hạn như FrobeniusSolvetrong Mathicala.

α - Để làm rõ điều này với một ví dụ, bạn cũng có thể thực hiện 43 bằng cách thực hiện 4 + 6 + 6 + 9 + 9 + 9 = 43 (319), nhưng điều này sẽ không tối ưu, và do đó, một đầu ra không chính xác, vì tổng bình phương nhỏ hơn kết hợp tôi đã lưu ý trong phần giới thiệu. Về cơ bản, tổng bình phương cao hơn = chi phí thấp hơn = hiệu quả nhất về chi phí.


Có giới hạn thời gian / bộ nhớ không?
Dennis

@Dennis Không có giới hạn thời gian hoặc bộ nhớ.
Kade

4
Đó thực sự là thứ Năm.
mbomb007

4
@ mbomb007 Quan sát sắc sảo: P Tôi đã điều chỉnh phần giới thiệu.
Kade

2
Tôi CẦN sử dụng định lý mcnugget gà bằng cách nào đó ...
Stretch Maniac

Câu trả lời:


7

Bình thường, 26 25 byte

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

Lưu ý rằng có một số ký tự không thể in được. Dùng thử trực tuyến: Trình diễn . Nó khá chậm (nhưng không chậm như giải pháp 26 byte của tôi).

Giải trình:

                          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

Bình thường, 32 byte

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

Lưu ý rằng có một số ký tự không thể in được. Dùng thử trực tuyến: Trình diễn Phiên bản này nhanh hơn nhiều. Nó tìm thấy giải pháp cho đầu vào [6,7,8]trong khoảng một giây và giải pháp cho đầu vào [30]trong khoảng 90 giây.

Giải trình:

                                 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

Tại sao nó bằng sqrt của tổng bình phương, chứ không phải chỉ là tổng?
mbomb007

1
@ mbomb007 Vì không thành vấn đề. Nếu a> b, hơn sqrt (a)> sqrt (b) và ngược lại. Và sử dụng .aphương pháp này ngắn hơn bình phương và tổng s^R2.
Jakube

5

Perl, 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":(";}

Đưa đầu vào từ các đối số của chương trình. In một :( nếu nó không thể tìm thấy một giải pháp hoàn hảo.

Mã bị hủy bỏ:

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 ":(";
}

PS: Đây có lẽ là mục đầu tiên không mất 10 phút cho 1 2;)

Kiểm tra nó ở đây.


Xin chúc mừng những gì dường như là chương trình nhanh nhất cho đến nay! Nó cũng có thể nhanh hơn chương trình tham khảo của tôi: P Tôi đã thêm một liên kết ideone ở cuối bài đăng của bạn để mọi người có thể thấy đầu ra.
Kade

Mã của bạn có thể tạo ra đầu ra không chính xác. Đầu vào 18nên in 9 9, không 4 4 10.
Dennis

Có đầu ra không chính xác khác là tốt. Nếu tôi không nhầm, bạn có thể sửa tất cả chúng bằng cách hoán đổi thứ tự 910.
Dennis

@Dennis Cảm ơn bạn, đã sửa nó!
Thomas Oltmann

3

CJam, 45 29 28 byte

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

Lưu ý rằng phương pháp này rất chậm và tốn nhiều bộ nhớ.

Hãy thử trực tuyến trong trình thông dịch CJam .

Nó có thể được tăng tốc đáng kể với chi phí 5 byte:

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

Độ phức tạp vẫn theo cấp số nhân của tổng đầu vào, nhưng điều này sẽ xử lý các trường hợp thử nghiệm lên tới 159 với trình thông dịch trực tuyến và tối đa 199 với trình thông dịch Java trong vài giây.

Hãy thử trực tuyến trong trình thông dịch CJam .

Ý kiến

Một mua tối ưu (tổng tối đa của hình vuông) là một sự mua hàng hợp lệ (số đúng cốm) có càng nhiều 40 's càng tốt, sau đó càng nhiều 20 ' s càng tốt, sau đó càng nhiều 9 's càng tốt (ví dụ, 9 9là thích hợp hơn 10 4 4) và cứ thế trong 10 ', 6 ' và 4 's.

Trong phương pháp này, chúng tôi tạo ra sản phẩm Cartesian gồm N bản sao của mảng [40 20 9 10 6 4 0] , trong đó N là số lượng cố định mong muốn. N là giới hạn trên (xấu) cho số lượng mua chúng ta phải thực hiện. Trong phiên bản tăng tốc của mã, chúng tôi sử dụng N / 40 + 4 thay thế.

Do cách sắp xếp mảng, sản phẩm của Cartesian sẽ bắt đầu bằng vectơ [40 ... 40] và kết thúc bằng vectơ [0 ... 0] . Chúng tôi tính toán chỉ số của vectơ đầu tiên có tổng chính xác (cũng sẽ có tổng bình phương tối ưu), truy xuất phần tử mảng tương ứng, loại bỏ các số 0 đóng vai trò giữ chỗ và in kết quả.

Nếu không tìm thấy vectơ nào, chỉ mục sẽ là -1 , vì vậy chúng tôi truy xuất [0 ... 0] , thay vào đó sẽ in một mảng trống.

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.

Đây có thể là một trong số ít tình huống giải quyết bằng tay nhanh hơn việc để mã hoàn thành .. công việc tốt đẹp bất kể :)
Kade

2

Julia, 126 byte

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))]))

Điều này tạo ra một hàm không tên, chấp nhận một mảng làm đầu vào và in một mảng hoặc boolean thành STDOUT, tùy thuộc vào việc một giải pháp có tồn tại hay không. Để gọi nó, đặt tên cho nó, vd f=n->....

Ungolfed + giải thích:

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

Ví dụ:

julia> f([1])
false

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

1

Python 3 - 265 ký tự

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)

Hiển thị khoảng cách:

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)

Vượt qua tất cả các trường hợp thử nghiệm

Lưu ý: Tôi không biết điều này sẽ vượt qua tất cả các trường hợp vì nó quá chậm ... Nhưng nó nên ...


Không có gì có vẻ sai với điều này ngay bây giờ, tôi sẽ kiểm tra nó và xem. Khi tôi về nhà, tôi sẽ thêm một tài liệu tham khảo, chương trình không được sử dụng mà tôi đã sử dụng để tạo danh sách trong Gist. Mặc dù tôi không định thời gian, tôi tin rằng nó mất khoảng 8-12 phút cho tất cả các trường hợp.
Kade

@ Vioz- Rực rỡ! : D
Beta Decay

Có vẻ như tôi có thể sai, sau khi thử nghiệm 36, nó đã vượt qua khoảng 40 triệu kết hợp (chính xác là 40.007.602) trước khi chạy vào MemoryError. Đây có thể là một hạn chế của máy công việc của tôi, vì nó chỉ có 4GB bộ nhớ.
Kade

@ Vioz- Hừm ... Thật vô vọng khi tôi tiếp tục thử nghiệm trên điện thoại của mình ...
Beta Decay

1
@undergroundmonorail Nếu bạn chỉ sử dụng một lần, thì với <= 4 ký tự, nhập thẳng sẽ tốt hơn (hòa vốn 5 lần). Nhưng nếu bạn đang sử dụng nó nhiều lần thì from blah import*luôn luôn tốt nhất. Ngoại lệ duy nhất tôi có thể nghĩ đến ở trên là nếu bạn có nhiều imports, đó là lần duy nhất xuất hiện trong tâm trí nơi asthực sự hữu ích.
Sp3000

1

JavaScript, 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

Tôi không chắc điều này có ổn không, có vẻ như nó hoạt động nhưng tôi chắc chắn đang thiếu thứ.

Nó dường như không chậm, mặc dù 123456nó xuất ra [40 x 3086, 10, 6]gần như ngay lập tức.

Giải trình:

Lặp lại các kích thước nugget (lớn nhất trước)

  • Nếu tổng của ngăn xếp cộng với kích thước nugget nhỏ hơn mục tiêu - 3 -> đẩy nó lên ngăn xếp
  • Nếu có hơn 40 trái -> đặt lại bộ đếm vòng lặp
  • Nếu tổng của ngăn xếp nhiều hơn mục tiêu khi đạt đến kích thước nugget cuối cùng -> bật phần tử cuối cùng, đặt lại bộ đếm vòng lặp
  • Nếu tổng của ngăn xếp cộng lại, trả về nó, nếu không trả về 0

Cho 199 | 1 ngăn xếp được xây dựng trông như thế này

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]

Cho 1

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

1
Cách tiếp cận của bạn dường như không kiểm tra nếu mục tiêu có thể đạt được. 11in [6]18in [10, 4].
Dennis

@Dennis Này, cảm ơn vì đã chỉ ra điều đó. Hôm qua là một đêm khuya. Đã sửa nó trong 5 ký tự. 18 in [10,4]vì tôi bị thiếu một cặp parens. Kiểm tra đã thực sự sai, tôi chỉ kiểm tra nếu có ít nhất một yếu tố trong tập kết quả, chứ không phải nếu nó tổng hợp chính xác. Tôi không biết những gì tôi nghĩ ở đó
C5H8NNaO4
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.