Collatz चचेरे भाई की गणना


21

सकारात्मक पूर्णांक n के लिए फ़ंक्शन f (n) को निम्नानुसार परिभाषित करें :

  • n / 2 , यदि n सम है
  • 3 * n + 1 , यदि n विषम है

यदि आप बार-बार इस फ़ंक्शन को 0 से अधिक किसी भी n पर लागू करते हैं , तो परिणाम हमेशा 1 में परिवर्तित होता है (हालांकि कोई भी अभी तक साबित नहीं कर पाया है)। इस संपत्ति को Collatz अनुमान के रूप में जाना जाता है ।

किसी पूर्णांक के रोक के समय को परिभाषित करें क्योंकि आपके पहुंचने से पहले आपको Collatz फ़ंक्शन f के माध्यम से इसे कितनी बार पास करना होगा । यहां पहले 15 पूर्णांकों के समापन समय हैं:

1  0
2  1
3  7
4  2
5  5
6  8
7  16
8  3
9  19
10 6
11 14
12 9
13 9
14 17
15 17

कॉलजेट चचेरे भाई के रूप में एक ही रोक समय के साथ संख्याओं के किसी भी सेट को कॉल करते हैं । उदाहरण के लिए, 5 और 32 Collatz चचेरे भाई हैं, 5 के एक रोक समय के साथ।

आपका कार्य: एक प्रोग्राम या फ़ंक्शन लिखना जो एक nonnegative पूर्णांक लेता है और Collatz चचेरे भाई के सेट को उत्पन्न करता है जिसका रोक समय उस पूर्णांक के बराबर है।

इनपुट

एक nonnegative पूर्णांक S, STDIN, ARGV या फ़ंक्शन तर्क के माध्यम से दिया जाता है।

उत्पादन

सभी नंबरों की एक सूची, जिसका रोक समय एस है, आरोही क्रम में क्रमबद्ध है । सूची आपके प्रोग्राम द्वारा आउटपुट हो सकती है, या आपके फ़ंक्शन द्वारा वापस या आउटपुट हो सकती है। आउटपुट स्वरूप लचीला है: अंतरिक्ष-अलग, न्यूलाइन-अलग, या आपकी भाषा का कोई भी मानक सूची प्रारूप ठीक है, जब तक कि संख्या एक दूसरे से आसानी से अलग हो जाती है।

आवश्यकताएँ

आपके सबमिशन को किसी भी S must 30 के लिए सही परिणाम देना चाहिए। इसे कुछ घंटों या दिनों में नहीं बल्कि कुछ सेकंड में समाप्त कर देना चाहिए।

उदाहरण

0  -> 1
1  -> 2
5  -> 5, 32
9  -> 12, 13, 80, 84, 85, 512
15 -> 22, 23, 136, 138, 140, 141, 150, 151, 768, 832, 848, 852, 853, 904, 906, 908, 909, 5120, 5376, 5440, 5456, 5460, 5461, 32768

यहाँ S = 30 के लिए आउटपुट का एक Gist दिया गया है ।

यह : बाइट्स जीत में सबसे छोटा कार्यक्रम। सौभाग्य!


क्या चक्र? मैंने चक्र परिहार का उल्लेख नहीं देखा। क्योंकि S = 5 के लिए, 3 मान हैं [4, 5, 32] क्योंकि आप "1 - 2 - 4 - 1 - 2- 4"
JPMC

1
@JPMC साइकिल परिहार समय को रोकने की परिभाषा से निहित है। 4 का रोक समय 2 है, 5 नहीं है, क्योंकि 2 है "1 तक पहुंचने से पहले आपको Collatz फ़ंक्शन के माध्यम से इसे पास करना होगा।"
DLosc

आह, मुझे माफ कर दो। मैं सोच रहा था कि एक संख्या कई बार रुक सकती है, क्योंकि कई रास्ते इसे ले जा सकते हैं। लेकिन यह 1 से निर्माण के संबंध में था, एन से काम नहीं करना। इसके बारे में क्षमा करें।
JPMC

1
@DLosc पायथ, बिल्कुल।
इसहाक

1
संबंधित, लेकिन गोल्फ नहीं: math.stackexchange.com/q/470782/20792 और math.stackexchange.com/q/1243841/20792
प्यूरफेरेट

जवाबों:


7

पायथ, 26 24 21 बाइट्स

Su+yMG-/R3fq4%T6G1Q]1

यह कोड तुरंत चलता है S=30। इसे स्वयं आज़माएँ: प्रदर्शन

5 बाइट बचाने के लिए @isaacg को धन्यवाद।

व्याख्या

मेरा कोड शुरू होता है 1और Collatz फ़ंक्शन को पूर्ववत करता है। यह कदम के सभी नंबरों dको मैप करता S-1है 2*dऔर (d-1)/3। पिछले एक हमेशा नहीं हालांकि वैध है।

                        implicit: Q = input number
                   ]1   start with G = [1]
 u                Q     apply the following function Q-times to G:
                          update G by
   yMG                      each number in G doubled
  +                       +
          fq4%T6G           filter G for numbers T, which satisfy 4==T%6
       /R3                  and divide them by 3
      -          1          and remove 1, if it is in the list
                            (to avoid jumping from 4 to 1)
S                       sort the result and print

इसका एक सुंदर उपयोग है -F
इसहाक

1
यदि आप - ... 1कम के अंदर राशि डालते हैं , तो आपको न तो कमी की जरूरत है .u, न ही -Fबाहर की। 2 वर्ण बचाता है।
इसहाक

@isaacg धन्यवाद मेरे पास वास्तव में पिछले संस्करण में था, लेकिन एक त्रुटि डिबगिंग के दौरान इसे हटा दिया।
Jakube

3
मैंने अपने जवाब के लिए @ isaacg से उधार लिया है। मैंने डुप्लिकेट को हटाने के लिए सबसे छोटा कोड खोजने की कोशिश में घंटों बिताए हैं, लेकिन यह अब तक का सबसे सुरुचिपूर्ण समाधान है। इसके अलावा, मैं वास्तव में अमान्य उद्धरणों को छोड़ने के लिए एक टपल का उपयोग पसंद करता हूं। अफसोस की बात है कि सीजेएम के पास टुपल्स नहीं हैं, लेकिन मैंने अमान्य उद्धरणों को 1 में मैप करने का प्रबंधन किया।
डेनिस

@Jakube q4%d6के बराबर है !%hhd6, लेकिन 1 वर्ण छोटा है।
isaacg

8

गणितज्ञ, 98 92 89 बाइट्स

यह समाधान S = 30तुरंत हल करता है:

(p={0};l={1};Do[l=Complement[##&@@{2#,Mod[a=#-1,2]#~Mod~3~Mod~2a/3}&/@l,p=p⋃l],{#}];l)&

यह एक अनाम फ़ंक्शन है जो Sअपने एकमात्र पैरामीटर के रूप में ले रहा है और Collatz चचेरे भाई की सूची लौटा रहा है।

एल्गोरिथ्म एक सरल चौड़ाई-पहली खोज है। किसी दिए गए Collatz चचेरे भाई Sसभी पूर्णांकों हैं जो Collatz चचेरे भाई के S-1माध्यम से 2*nया विषम संख्या के माध्यम से पहुंचा जा सकता है (n-1)/3। हमें यह भी सुनिश्चित करने की आवश्यकता है कि हम केवल उन पूर्णांकों का उत्पादन करते हैं जो कदमों के बाद पहली बार पहुंच गए थे S, इसलिए हम पिछले सभी चचेरे भाइयों का ट्रैक रखते हैं pऔर उन लोगों को परिणाम से हटा देते हैं। चूँकि हम वैसे भी कर रहे हैं, हम कुछ बाइट्स को बचाने के लिए सभी पिछले चचेरे भाई (केवल उन लोगों से S-1) के चरणों की गणना करके कुछ बाइट्स को बचा सकते हैं (जो इसे थोड़ा धीमा बनाता है, लेकिन आवश्यक रूप से ध्यान देने योग्य नहीं है S)।

यहाँ थोड़ा अधिक पठनीय संस्करण है:

(
  p = {0};
  l = {1};
  Do[
    l = Complement[
      ## & @@ {2 #, Mod[a = # - 1, 2] #~Mod~3~Mod~2 a/3} & /@ l,
      p = p ⋃ l
    ]~Cases~_Integer,
    {#}
  ];
  l
) &

5

पायथन 2, 86 83 75 73 71 बाइट्स

f=lambda n,k=1:sorted([k][n:]or(k>4==k%6and f(n-1,k/3)or[])+f(n-1,k*2))

जैसे बुलाओ f(30)n = 30बहुत तुरंत है।

( kचचेरे भाई की सूची के बजाय एक संख्या होने के कारण @DLosc के लिए धन्यवाद , और कुछ बाइट्स। छोड़ने के लिए @isaacg को धन्यवाद ~-।)

यह संस्करण बहुत छोटा है, लेकिन दुर्भाग्यवश घातांक शाखाओं के कारण बहुत लंबा हो जाता है:

f=lambda n,k=1:sorted([k][n:]or(k>4==k%6)*f(n-1,k/3)+f(n-1,k*2))

दिलचस्प है - मेरा मूल समाधान बहुत समान है, लेकिन (आपकी ओर से कुछ अनुकूलन) लेने से 2 बाइट्स छोटे हो जाते हैं f=lambda d,n=1:d and sorted(sum((c(d-1,x)for x in[n*2]+[~-n/3][:n>4==n%6]),[]))or[n]:। यह फ़ंक्शन कॉल के साथ कम कुशल है, लेकिन फिर भी n = 30एक सेकंड के भीतर है।
DLosc

1
@ डलॉक मुझे आपका विचार पसंद आया और इसे एक बेहतर बना दिया :)
Sp3000

अच्छा! यहाँ 2 और बाइट्स बंद हैं:f=lambda n,k=1:sorted([k][n:]or(k>4==k%6and f(n-1,~-k/3)or[])+f(n-1,k*2))
DLosc

@DLosc अहा धन्यवाद मैं अभी भी कसम खाता हूँ कि वहाँ एक बेहतर शॉर्ट-
सर्कुलेटिंग

मुझे लगता है ~-कि अनावश्यक है क्योंकि आप पूर्णांक विभाजन का उपयोग कर रहे हैं।
isaacg

5

सीजेएम, 29 26 बाइट्स

Xari{{2*_Cmd8=*2*)}%1-}*$p

प्रत्येक पुनरावृत्ति के बाद 1 को हटाने के लिए अपने विचार के लिए श्रेय @isaacg को जाता है, जिसने मुझे दो बाइट्स सीधे और एक दूसरे को अप्रत्यक्ष रूप से बचाया।

CJam दुभाषिया में इसे ऑनलाइन आज़माएं (एक सेकंड से भी कम समय में समाप्त होना चाहिए)।

यह काम किस प्रकार करता है

Xa       e# Push A := [1].
ri{      e# Read an integer from STDIN and do the following that many times:
  {      e# For each N in A:
    2*   e#     Push I := (N * 2) twice.
    _Cmd e#     Push (I / 12) and (I % 12).
     8=  e#     Push K := (I % 12 == 8).

         e#     (K == 1) if and only if the division ((N - 1) / 3) is exact and
         e#     yields an odd integer. In this case we can compute the quotient 
         e#     as (I / 12) * 2 + 1.

    *2*) e#     Push J := (I / 12) * K * 2 + 1.

         e#     This yields ((N - 1) / 3) when appropriate and 1 otherwise.
  }%     e# Replace N with I and J.
  1-     e# Remove all 1's from A.

         e# This serves three purposes:

         e# 1. Ones have been added as dummy values for inappropriate quotients.

         e# 2. Not allowing 1's in A avoids integers that have already stopped
         e#    from beginning a new cycle. Since looping around has been prevented,
         e#    A now contains all integers of a fixed stopping time.

         e# 3. If A does not contain duplicates, since the maps N -> I and N -> J
         e#      are inyective (exluding image 1) and yield integers of different
         e#      parities, the updated A won't contain duplicates either.

}*       e#
$p       e# print(sort(C))

4

सीजेएम, 35 बाइट्स

1]ri{_"(Z/Y*"3/m*:s:~\L+:L-_&0-}*$p

स्पष्टीकरण जल्द ही आ रहा है। यह "सुंदर स्ट्रेट फ़ॉरवर्ड" दृष्टिकोण (इसे संपादित इतिहास में देखें) की तुलना में बहुत तेज़ संस्करण है।

इसे ऑनलाइन यहाँ आज़माएँ , N = 30जिसके लिए ऑनलाइन संस्करण में सेकंड में और तुरंत जावा कम्पाइलर में चलता है


बड़े इनपुट के लिए कितना समय लगेगा? It should finish in seconds or minutes, not hours or days.
DLosc

ओह समझा। पायथन संस्करण जो मैंने लिखा था, एन = 30 के लिए लगभग 5 घंटे लग रहे थे।
DLosc

नवीनतम संस्करण लगभग तुरन्त चलता है।
ऑप्टिमाइज़र

6
आपके कोड में एक बग है। परीक्षण-मामला S=15काम नहीं करता है।
जकुबे २

3

जावा 8, 123

x->java.util.stream.LongStream.range(1,(1<<x)+1).filter(i->{int n=0;for(;i>1;n++)i=i%2<1?i/2:3*i+1;return n==x;}).toArray()

जब x30 वर्ष का होता है, तो कार्यक्रम में 15 मिनट और 29 सेकंड लगते हैं।

विस्तारित

class Collatz {
    static IntFunction<long[]> f =
            x -> java.util.stream.LongStream.range(1, (1 << x) + 1).filter(i -> {
                int n = 0;
                for (; i > 1; n++)
                    i = i % 2 < 1 ? i / 2 : 3 * i + 1;
                return n == x;
            }).toArray();

    public static void main(String[] args) {
        System.out.println(Arrays.toString(f.apply(15)));
    }
}

बस जिज्ञासु, यह एस = 30 के लिए कितना समय लेता है?
जियोबिट्स

यह केवल जावा 8 में काम करता है, सही है? javac 1.7.0_79उबंटू का उपयोग करने से मुझे बहुत सी वाक्यविन्यास त्रुटियां हुईं।
DLosc

@ डलास करेक्ट; उस पोस्ट में उल्लेख करूँगा।
यपनिप

i > 1 && ++n <= x(आप भी ड्रॉप कर सकते n++हैं) लूप टर्मिनल की स्थिति पर प्रतिबंध लगाते हुए सिर्फ 5 और पात्रों के लिए और भी तेज लगता है ... मेरे लिए S = 30 के लिए लगभग 3 मिनट। अगर मैं .parallel()भी शामिल करूं, तो एक मिनट के लिए सुरक्षित रूप से मुंडा जा सकता हूं , लेकिन चूंकि यह कोड-गोल्फ है ...
hjk

1

पायथन 2, 118 बाइट्स

खैर, मुझे लगा कि मैं @ Sp3000 के समाधान को देखने के बाद सर्वश्रेष्ठ पायथन स्कोर तक नहीं पहुंच पाऊंगा। लेकिन यह एक छोटी सी समस्या की तरह लग रहा था, इसलिए मैं वैसे भी एक स्वतंत्र समाधान की कोशिश करना चाहता था:

s={1}
for k in range(input()):
 p,s=s,set()
 for t in p:s.add(2*t);t>4and(t-1)%6==3and s.add((t-1)/3)
print sorted(s)

व्हॉट्सएप छीनने से पहले एक ही बात:

s={1}
for k in range(input()):
    p,s=s,set()
    for t in p:
        s.add(2 * t)
        t > 4 and (t - 1) % 6 == 3 and s.add((t - 1) / 3)
print sorted(s)

यह चौड़ाई खोज का पहला प्रत्यक्ष कार्यान्वयन है। प्रत्येक चरण में, हमारे पास समय रोकने के साथ सेट होता है k, और सेट k + 1से प्रत्येक मूल्य के संभावित पूर्ववर्तियों tको कदम से जोड़कर सेट को रोक दिया जाता है k:

  • 2 * t हमेशा एक संभावित पूर्ववर्ती है।
  • यदि के tरूप में लिखा जा सकता है 3 * u + 1, जहां uएक विषम संख्या है जो नहीं है 1, तो uएक पूर्ववर्ती भी है।

N = 30मेरे मैकबुक प्रो पर चलने के लिए लगभग 0.02 सेकंड का समय लगता है ।


सामान्य तौर पर, s.add(x)एक गोल्फ में अनावश्यक है क्योंकि आप आमतौर पर इसके s|={x}बजाय कर सकते हैं । इसके अलावा, कोष्ठक पर सहेजने के ~-xबजाय का उपयोग करना (x+1)। लेकिन अन्यथा, अच्छी नौकरी :)
Sp3000

@ Sp3000 धन्यवाद। मैं आसानी से दूसरा स्थान नहीं ले सकता s.add()क्योंकि यह एक असाइनमेंट बन जाता है, और अब अभिव्यक्ति का हिस्सा नहीं हो सकता। यह पहले एक के लिए काम करता है। forकाउंटर के आधार पर छोरों हमेशा तरह वर्बोज़ के रूप में अच्छी तरह कर रहे हैं। मुझे लगा कि मैं एक whileलूप का उपयोग करके इसे छोटा कर सकता हूं , लेकिन यह बिल्कुल समान लंबाई वाला निकला।
रेटो कोराडी

forलूप के बजाय , चूंकि आप किसी अन्य तरीके से इनपुट का उपयोग नहीं करते हैं, शायद आप exec"..."*input()इसके बजाय कर सकते हैं :)
Sp3000

1

PHP 5.4+, 178 बाइट्स

कार्यक्रम

function c($s,$v=1,$p=[],&$r=[]){$p[]=$v;if(!$s--){return$r[$v][]=$p;}c($s,$v*2,$p,$r);is_int($b=($v-1)/3)&!in_array($b,$p)&$b%2?c($s,$b,$p,$r):0;ksort($r);return array_keys($r);}

परीक्षण और आउटपुट

echo "0 - ".implode(',',c(0)).PHP_EOL;
// 0 - 1
echo "1 - ".implode(',',c(1)).PHP_EOL;
// 1 - 2
echo "5 - ".implode(',',c(5)).PHP_EOL;
// 5 - 5,32
echo "9 - ".implode(',',c(9)).PHP_EOL;
// 9 - 12,13,80,84,85,512
echo "15 - ".implode(',',c(15)).PHP_EOL;
// 15 - 22,23,136,138,140,141,150,151,768,832,848,852,853,904,906,908,909,5120,5376,5440,5456,5460,5461,32768

एस (30) 0.24 सेकंड * में चलता है , 732 तत्व देता है। एक जोड़े हैं

86,87,89,520,522,524,525,528, [ ... ] ,178956928,178956960,178956968,178956970,1073741824

* बाइट्स पर बचाने के लिए, मैं जोड़ने के लिए किया था ksortऔर array_keysहर कदम पर। केवल अन्य विकल्प मैं था कि कॉल एक छोटा सा आवरण समारोह बनाने के लिए था c()और उसके बाद कॉल array_keysऔर ksortपरिणाम पर एक बार। लेकिन समय अभी भी शालीनता से दुखी होने के कारण, मैंने प्रदर्शन को कम बाइट की गिनती के लिए लेने का फैसला किया। उचित छँटाई और प्रसंस्करण के बिना, समय एस (30) के लिए औसतन 0.07 सेकंड है

यदि किसी के पास बहुत अधिक अतिरिक्त बाइट्स के बिना केवल एक बार उचित प्रसंस्करण प्राप्त करने का कोई चतुर तरीका है, तो कृपया मुझे बताएं! (मैं अपनी संख्या सरणी कुंजियों के रूप में संग्रहीत करता हूं, इसलिए इसका उपयोग array_keysऔर ksort)


0

सी भाषा

#include <stdio.h>
#include <limits.h>    
const int s = 30;

bool f(long i)
{
    int r = 0;
    for(;;)
        if (i < 0 || r > s) return false;
        else if (i == 1) break;
        else{r ++;i = i % 2 ? 3*i + 1 : i/2;}
    return (r==s);
}

void main(){
    for(long i = 1; i < LONG_MAX; i++) if (f(i)) printf("%ld ", i);
}

5
नमस्कार और PPCG में आपका स्वागत है! चूंकि यह एक कोड-गोल्फ प्रतियोगिता है, आप अपने कोड को यथासंभव छोटा बनाना चाहेंगे। इसके अलावा, कृपया अपनी पोस्ट में भाषा का नाम शामिल करें।
एलेक्स ए।

आप {}अपने कोड को प्रारूपित करने के लिए बटन दबा सकते हैं , जो मैंने आपके लिए किया है। लेकिन जैसा कि एलेक्स कहते हैं, कृपया भाषा का नाम (C) जोड़ें और इसे गोल्फ बनाने की कोशिश करें :) लेकिन स्वागत है!
Sp3000

प्रारूप कोड की मदद करने के लिए @ Sp3000 धन्यवाद
तूफानी

कार्य fठीक से व्यवहार नहीं कर रहा है। के साथ s=5, मुझे गलत परिणाम का एक गुच्छा मिलता है। if (r == s)return true;तब से होना चाहिए return (r==s), जब fसे कोई भी रिटर्निंग नहीं होगी (r < s)। इसके अलावा, मुझे लगता है कि आप यह घोषणा करनी चाहिए iमें fके रूप में longहै, क्योंकि यह कुछ मान के लिए बहुत जल्दी अतिप्रवाह होगा।
डेनिस

@Dennis धन्यवाद :) यह होना चाहिएreturn (r==s);
तूफानी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.