Tìm tất cả các cặp số có tổng bằng 121212 [đã đóng]


8

Vấn đề này khá dễ thực hiện bằng vũ lực. Trên thực tế, nó cũng sẽ nhanh chóng hợp lý để vũ phu. Nhưng đâu là niềm vui trong đó?

Vấn đề

Tạo một danh sách tất cả các cặp số gồm 5 chữ số duy nhất 121212. Tuy nhiên, mỗi chữ số thập phân phải xuất hiện chính xác một lần trong một trong hai số. Vì vậy, một cặp hợp lệ sẽ được (98167, 23045). Nhưng một cặp không hợp lệ sẽ được (23456, 97756)7, 5, 6được lặp đi lặp lại nhiều hơn một lần, và1, 8, 0 không được sử dụng ở tất cả. Có chính xác 192 cặp duy nhất.

Quy tắc

  1. Hiệu quả: Bạn có thể vũ phu này. Nhưng đó là chuyện nhỏ để làm. Vì vậy, thay vào đó, thách thức thực sự ở đây là tìm ra cách sản xuất hiệu quả danh sách các con số.

  2. Yêu cầu về mã nguồn: Nó không thể lưu trữ danh sách số (hoặc bất kỳ phần nào của nó). Trình tự số phải được tạo ra khi đang bay.

Chúc vui vẻ!


1
Tôi có bỏ lỡ phần mà bạn nói "Giả sử cơ sở 10" không? ;)
kojiro 17/03/2016

1
@kojiro: BẠN có bao nhiêu ngón tay? :-)
mellamokb

1
@kojiro: Không. Nếu bạn có thể tìm thấy các căn cứ khác nơi nó hoạt động, bằng mọi cách ... tôi nghĩ điều đó sẽ thật tuyệt vời!
ircmaxell

@kojiro loại: " mỗi chữ số thập phân phải xuất hiện ... " mặc dù có vẻ như bạn có thể tìm thấy hai số hex 5 chữ số miễn là chúng không chứa AF
Cephalepad

@mellamokb 10 ngón tay, nhưng tôi có 20 chữ số.
kojiro

Câu trả lời:


6

JavaScript

function findpairs(arrin1,arrin2){
    functioncount++
    var arr1=[]
    var arr2=[]
    var strike=[]
    var overflow=0
    var b
    var len=arrin1.length
    for(var a=0;a<len;a++){
        arr1[a]=arrin1[a]
        arr2[a]=arrin2[a]
        strike[arr1[a]]=true
        strike[arr2[a]]=true
        overflow=+((arr1[a]+arr2[a])>9)
    }
    var desired=12-(len%2)-overflow
    for(a=9;a>0;a--){
        b=(desired-a)%10
        if(a>b && !strike[a] && !strike[b]){
            if(len==4){
                if((a+b)>9){
                    document.write(""+a+arr1[3]+arr1[2]+arr1[1]+arr1[0]+" "+b+arr2[3]+arr2[2]+arr2[1]+arr2[0]+"<br>")
                    document.write(""+a+arr1[3]+arr1[2]+arr1[1]+arr2[0]+" "+b+arr2[3]+arr2[2]+arr2[1]+arr1[0]+"<br>")
                    document.write(""+a+arr1[3]+arr1[2]+arr2[1]+arr1[0]+" "+b+arr2[3]+arr2[2]+arr1[1]+arr2[0]+"<br>")
                    document.write(""+a+arr1[3]+arr1[2]+arr2[1]+arr2[0]+" "+b+arr2[3]+arr2[2]+arr1[1]+arr1[0]+"<br>")
                    document.write(""+a+arr1[3]+arr2[2]+arr1[1]+arr1[0]+" "+b+arr2[3]+arr1[2]+arr2[1]+arr2[0]+"<br>")
                    document.write(""+a+arr1[3]+arr2[2]+arr1[1]+arr2[0]+" "+b+arr2[3]+arr1[2]+arr2[1]+arr1[0]+"<br>")
                    document.write(""+a+arr1[3]+arr2[2]+arr2[1]+arr1[0]+" "+b+arr2[3]+arr1[2]+arr1[1]+arr2[0]+"<br>")
                    document.write(""+a+arr1[3]+arr2[2]+arr2[1]+arr2[0]+" "+b+arr2[3]+arr1[2]+arr1[1]+arr1[0]+"<br>")
                    document.write(""+a+arr2[3]+arr1[2]+arr1[1]+arr1[0]+" "+b+arr1[3]+arr2[2]+arr2[1]+arr2[0]+"<br>")
                    document.write(""+a+arr2[3]+arr1[2]+arr1[1]+arr2[0]+" "+b+arr1[3]+arr2[2]+arr2[1]+arr1[0]+"<br>")
                    document.write(""+a+arr2[3]+arr1[2]+arr2[1]+arr1[0]+" "+b+arr1[3]+arr2[2]+arr1[1]+arr2[0]+"<br>")
                    document.write(""+a+arr2[3]+arr1[2]+arr2[1]+arr2[0]+" "+b+arr1[3]+arr2[2]+arr1[1]+arr1[0]+"<br>")
                    document.write(""+a+arr2[3]+arr2[2]+arr1[1]+arr1[0]+" "+b+arr1[3]+arr1[2]+arr2[1]+arr2[0]+"<br>")
                    document.write(""+a+arr2[3]+arr2[2]+arr1[1]+arr2[0]+" "+b+arr1[3]+arr1[2]+arr2[1]+arr1[0]+"<br>")
                    document.write(""+a+arr2[3]+arr2[2]+arr2[1]+arr1[0]+" "+b+arr1[3]+arr1[2]+arr1[1]+arr2[0]+"<br>")
                    document.write(""+a+arr2[3]+arr2[2]+arr2[1]+arr2[0]+" "+b+arr1[3]+arr1[2]+arr1[1]+arr1[0]+"<br>")
                    resultcount+=16
                }
            }
            else{
                arr1[len]=a
                arr2[len]=b
                findpairs(arr1,arr2)
            }
        }
    }
}
resultcount=0
functioncount=0
start=+new Date()
findpairs([],[])
end=+new Date()
document.write("<br>"+resultcount+" results<br>"+(end-start)+" ms<br>"+functioncount+" function calls")

Được lưu trữ tại: http://ebusiness.hopto.org/findpairs.htm

Nhận thức toán học: Nếu bạn có một cặp, 15 cặp khác có thể được tạo một cách tầm thường bằng cách hoán đổi các chữ số giữa hai số, do đó tôi chỉ tìm kiếm các số trong đó các chữ số của số thứ nhất đều lớn hơn chữ số của số thứ hai, và sau đó chỉ cần xuất ra tất cả hoán vị.

Tôi bắt đầu từ các chữ số có nghĩa ít nhất và tạo ra chuỗi dưới dạng cây ngang, cho mỗi bước khẳng định rằng kết quả trung gian là chính xác và không có chữ số nào được sử dụng hai lần. Với các phương thức này, hàm chỉ cần được gọi tổng cộng 50 lần. Trên máy của tôi, Chrome mang lại kết quả thời gian chạy thường là 2 ms.


8

C ++

#include<iostream>
using namespace std;
#include<algorithm>

int main()
{
    long long N,F,S;
    char str[11]="1023456789";
    while (1) {
        sscanf(str,"%lld",&N);
        F=N/100000;S=N%100000;
        if (F>60000)
           break;
        if (F+S==121212)
           printf("%lld %lld\n",F,S);
        next_permutation(str,str+10);
    }
}

http://www.ideone.com/Lr84g


2
Rất thú vị. Vì vậy, bạn đang lặp đi lặp lại trên tất cả các hoán vị có thể có trong đó phần trên nhỏ hơn 60001 (khoảng 1.768.168 lần lặp, hoặc ít hơn một chút 10!/2) và sau đó kiểm tra xem nó có thể đạt tới 121212 hay không. Nhưng tôi vẫn tò mò liệu chúng ta có thể làm việc hiệu quả hơn không ...
ircmaxell 17/03/2016

Hmm, tôi nghĩ rằng bạn không được phép lưu trữ danh sách số ... Phrasing mơ hồ?
bltxd 17/03/2016

@bltxd: Ý tôi là lưu trữ nó trước khi ra tay. Bạn có thể lưu trữ nó khi bạn tạo ra nó. Nhưng bạn không thể lưu trữ đó (51430, 69872)là một cặp hợp lệ. Bạn có thể lưu trữ trước danh sách chữ số ( 0123456789) và tổng ( 121212).
ircmaxell 17/03/2016

Tôi đồng ý rằng đó không phải là cách hiệu quả nhất để làm điều đó, nhưng tôi hy vọng nó khác.
fR0DDY 17/03/2016

4

Con trăn 2.

Nó khá hiệu quả vì nó xây dựng các con số (vòng lặp bên trong nhất được thực hiện tổng cộng 4570 lần) và khá ngắn vì tôi đã chơi golf một chút (201 ký tự), nhưng tôi không thực sự chắc chắn muốn giải thích điều này :)

p=lambda t,a,d:((x,y)for x in range(10)for y in[(t-x-a)%10]if(x not in d)&(y not in d)and x-y)
w=lambda s:[s]if len(s)==10and s[:5]<s[5:]else(m for n in p(2-len(s)/2%2,sum(s[-2:])/10,s)for m in w(s+n))

Tuy nhiên, các giá trị được trả về khá đặc biệt: gọi wvới một bộ dữ liệu trống và bạn nhận được một bộ lặp gồm 10 bộ. 10 bộ dữ liệu này là chữ số của hai số, than ôi ngượcxen kẽ , tức là bộ

(2, 0, 8, 3, 7, 4, 9, 1, 6, 5)

đại diện cho các số 51430 và 69782.

Kiểm tra:

result = list(w(()))

assert len(set(result)) == 192               # found all values
assert len(result) == 192                    # and no dupes 

for digits in result:
    assert all(0 <= d <= 9 for d in digits)  # real digits -- zero through nine
    assert len(set(digits)) == 10            # all digits distinct

    n1 = int("".join(map(str, digits[9::-2])))
    n2 = int("".join(map(str, digits[8::-2])))

    assert n1 + n2 == 121212                 # sum is correct

Đây là phiên bản chưa được chỉnh sửa:

ppcalls = 0       # number of calls to possiblePairs
ppyields = 0      # number of pairs yielded by possiblePairs
ppconstructed = 0 # number of construced pairs; this is the number
                  #     of times we enter the innermost loop

def possiblePairs(theirSumMod10, addition, disallowed):
    global ppcalls, ppyields, ppconstructed
    ppcalls += 1
    for a in range(10):
        b = (theirSumMod10 - a - addition) % 10
        ppconstructed += 1
        if a not in disallowed and b not in disallowed and a != b:
            ppyields += 1
            yield (a, b)

def go(sofar):
    if len(sofar) == 10:
        if sofar[:5] < sofar[5:]: # dedupe
            yield sofar

    digitsum = 2 - (len(sofar) / 2) % 2 # 1 or 2, alternating

    for newpair in possiblePairs(digitsum, sum(sofar[-2:]) / 10, sofar):
        for more in go(sofar + newpair):
            yield more


list(go(()))        # iterate

print ppcalls       # 457
print ppyields      # 840
print ppconstructed # 4570

3

C

#include <stdio.h>

int mask(int n)
{
    int ret = 0;

    for (; n > 0; n /= 10)
        ret |= 1 << n % 10;

    return ret;
}

int main(void)
{
    int a, b;

    for (a = 21213, b = 99999; a < b; a++, b--)
        if ((mask(a) | mask(b)) == 0x3FF)
            printf("%d %d\n", a, b);

    return 0;
}

Điều này đi qua tất cả các cặp số có 5 chữ số có tổng bằng 121212 (nghĩa là 39393 lần lặp hoặc ~ 1/46 số lần lặp được sử dụng bởi câu trả lời của fR0DDY ). Đối với mỗi cặp, nó tạo thành một mặt nạ bit của các chữ số trong mỗi số, sau đó xem nếu chúng HOẶC 0b1111111111.


Nếu bạn thêm 10 lần lặp cho mặt nạ mỗi lần, nó sẽ khiến độ phức tạp thời gian chỉ tốt hơn ~ 1/5 lần sau đó là của tôi. :)
fR0DDY 17/03/2016

2

Javascript (481)

function m(d,i){o=d-i;if(0<=o&&o<=9&&o!=i)return o;o+=10;if(0<=o&&o<=9&&o!=i)return o;return}function p(n,a){x=0;r=[];d=n%10;for(i=0;i<10;i++){if((!a||!a.contains(i))&&(o=m(d,i))&&(!a||!a.contains(o))&&i+o<=n)r[x++]=[i,o]}return r}function f(n,a){var x=0;var r=[];var d=p(n,a);for(var i=0;i<d.length;i++){var s=Math.floor((n-d[i][0]-d[i][1])/10);if(s>0){var t=f(s,d[i].concat(a));for(var j=0;j<t.length;j++)r[x++]=[t[j][0]*10+d[i][0],t[j][1]*10+d[i][1]]}else{r[x++]=d[i]}}return r}

http://jsfiddle.net/XAYr3/4/

Ý tưởng cơ bản: tạo kết hợp các chữ số hợp lệ có thể được sử dụng trong cột ngoài cùng bên phải. Chẳng hạn, (0,2), (3,9), (4,8), (5,7). Đối với mỗi kết hợp, hãy tìm đệ quy các cặp hoạt động cho chữ số tiếp theo từ bên phải, mà không trùng lặp các chữ số trong cặp đầu tiên. Lặp lại cho đến khi một cặp số gồm 5 chữ số được tạo. Kết hợp tất cả các kết quả đó thành một mảng duy nhất và danh sách là 192 phần tử. Điều này tôi tin rằng nên yêu cầu về số lần lặp ít nhất, nhưng tất cả các phân bổ / phân bổ mảng làm cho tổng thể nó thực tế không hiệu quả.

Các thử nghiệm đếm của tôi cho thấy hàm fđược gọi là 310 lần, vòng lặp bên trong iđược thực hiện tổng cộng 501 lần (trên tất cả các cuộc gọi đến f) và vòng lặp bên trong jđược thực hiện tổng cộng 768 lần (trên tất cả mọi thứ).


1

Con trăn, 171 ký tự

def R(x,y,d,c):
 if not d and x<y:print x,y
 for p in d:
  q=(12-c%2-p-(x+y)/10**c)%10
  if p-q and q in d:R(x+p*10**c,y+q*10**c,d-set([p,q]),c+1)
R(0,0,set(range(10)),0)

Mã duy trì bất biến mà x, yc chữ số và tất cả các chữ số không sử dụng đều nằm trong tập hợpd .

Thói quen Rđược gọi là tổng cộng 841 lần, khá hiệu quả.


0

C ++

#include<iostream>
using namespace std;
#include<algorithm>
#include<cstring>

int main()
{
        int i;
        char str1[11]="0123456789",str2[11];
        for (i=99999;i>60000;i--)
        {
                sprintf(str2,"%d%d",i,121212-i);
                sort(str2,str2+10);
                if(!strcmp(str1,str2))
                        printf("%d %d\n",i,121212-i);
        }
}

http://www.ideone.com/Lr84g

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.