Drucken Sie den Schnittpunkt von Sequenzen

9

Sequenzen

Sie erhalten vier 1durch nummerierte Zahlenfolgen 4.

  1. OEIS Der Ort 0, an dem die natürlichen Zahlen binär aufgelistet sind. Hier ist ein Beispiel für die Berechnung der Sequenz:

     0,1,10,11,100,101,110,111
     ^    ^     ^^  ^    ^
     0    3     78  10   14
    

    Der Beginn der Sequenz sieht folgendermaßen aus: 0, 3, 7, 8, 10, 14, 19, 20, 21, 23, 24, 27, 29, 31, 36, 37, 40, 45, 51, ...


  1. OEIS Diese Sequenz enthält die erste natürliche Zahl, überspringt die nächsten zwei, enthält dann die nächsten drei, überspringt dann die nächsten vier und fährt fort.

     0, 3, 4, 5, 10, 11, 12, 13, 14, 21, 22, 23, 24, 25, 26, 27, 36, ...
    

  1. OEIS Positive ganze Zahlen , wo sowohl die Anzahl der 0‚s und die Anzahl der 1‘ s in der binären Darstellung der Zahl sind Kräfte der 2.

    2, 4, 5, 6, 9, 10, 12, 16, 23, 27, 29, 30, 33, 34, 36, 39,
    

  1. OEIS Die Hofstadter Q- Sequenz .

    a (1) = a (2) = 1;
    a (n) = a (na (n-1)) + a (na (n-2)) für n> 2.

    1, 1, 2, 3, 3, 4, 5, 5, 6, 6, 6, 8, 8, 8, 10, 9, 10, 11, 11, 12, 12, 12, 12, 16, 14, ...
    

    Über diese Sequenz ist wenig streng bewiesen, aber es gibt viele empirische Ergebnisse. Eines ist besonders wichtig, und Sie können davon ausgehen, dass es für die gesamte Serie gilt:

    In diesem Artikel wurde festgestellt, dass die Elemente der Serie in Generationen eingeteilt werden können. Wenn wir sie ab 1 nummerieren, enthält die k- te Generation genau 2 k Elemente. Die relevante Eigenschaft ist, dass alle Zahlen in der Generation k erhalten werden, indem zwei Zahlen aus den Generationen k-1 und / oder k-2 summiert werden , jedoch niemals aus früheren Generationen. Sie können diese (und nur diese) Beobachtung verwenden, um eine Untergrenze für die verbleibenden Elemente in der Sequenz festzulegen.


Herausforderung

Ihre Herausforderung besteht darin, die erste zu drucken x Zahlen im Schnittpunkt der angegebenen Eingabesequenzen .

Eingabe: Zwei durch ein Leerzeichen getrennte Zahlen STDIN. Die erste Zahl ist eine ganze Zahl von 1bis 15einschließlich, wobei jedes Bit einer Sequenz entspricht. Das niedrigste Bit entspricht der Sequenz 1und das höchste entspricht der Sequenz 4. Die zweite ist die Anzahl der Zahlen x, auf die ausgegeben werden sollSTDIN .

Ausgabe: Die ersten xZahlen, die sich mit den angegebenen Eingabesequenzen überschneiden. Drucken Sie die Zahlen aufSTDOUT mit einem klaren Leerzeichen oder einer Interpunktion als Trennzeichen (Leerzeichen, Tabulatoren, Zeilenumbrüche, Kommas, Doppelpunkte, Punkte usw.) auf.


Beispiele

1. Drucken Sie die ersten 3Zahlen in jeder Sequenz.

Eingang: 15 3

Ausgabe: 10,23,40


2. Drucken Sie die ersten 12Zahlen in der Sequenznummer1 und 4.

Eingang: 9 12

Ausgabe: 3,8,10,14,19,20,21,23,24,31,37,40


3. Drucken Sie die erste10 Zahlen nacheinander aus2 .

Eingang: 2 10

Ausgabe: 0,3,4,5,10,11,12,13,14,21


4. Drucken Sie die ersten 6Zahlen in Sequenzen 3und4 .

Eingang: 12 6

Ausgabe: 2,4,5,6,9,10


Einzelheiten

  • Sie können die Ausgabe nach Belieben oder am Ende auf einmal drucken.

Vielen Dank an alle, die im Chat dabei geholfen haben! Diese Frage profitierte stark davon, im Sandkasten zu sein .

hmatt1
quelle
@chilemagic: Wie definiert man eigentlich "erste X-Zahlen" in einer Kreuzung? Wenn Sie beide Sequenzen im 12 5Beispiel auf den gleichen Index bringen, kommt sie dann 10tatsächlich 9in der Kreuzung vor ... Wie würden Sie beim Durchlaufen der Sequenzen entscheiden, ob Sie die 9Nummer 3 als mögliche Kreuzung überspringen möchten ? Als ob # 3 7drin wäre, müssten Sie es überspringen, da dies nicht in # 4
Claudiu
@Claudiu Ihre ausgegebenen Zahlen sollten immer zunehmen, und jede Zahl würde nur einmal in Ihrer Ausgabe erscheinen.
hmatt1
Gibt es eine Höchstgrenze für x?
Ypnypn
@ypnypn codiert kein Limit fest, aber wenn Ihr Algorithmus sehr langsam ist oder für sehr große Eingaben nicht fertig wird, ist das in Ordnung. Dies ist Code Golf, so dass Sie ineffizient sein können, um Bytes zu sparen.
hmatt1

Antworten:

2

Haskell, 495 442 402

import Data.List
d=1:1:1%2
f=filter
p 0="0"
p 1="1"
p n=p(div n 2)++p(mod n 2)
l=length
u z[a,b]=sort.head.dropWhile((<b).l)$m(nub.foldl1 intersect.y(tail.p$31-a).(`m`[d,f(v.group.sort.p)[1..],z#1,y(z>>=p)z]).take)z
w=(=='0')
v[a]=1>2
v x=all(all w.tail.p.l)x
y x=m snd.f(w.fst).zip x
x#n=n`take`x++drop(n+n+1)x#(n+2)
n%m=d!!(m-d!!n)+d!!(m-d!!(n-1)):m%(m+1)
main=interact$show.u[0..].m read.words
m=map

Es funktioniert ziemlich gut. Hier einige Beispiele von OP:

Flonk@home:~>echo 15 10 | codegolf
[10,23,40,57,58,139,147,149,212,228]
Flonk@home:~>echo 9 12 | codegolf
[3,8,10,14,19,20,21,23,24,31,37,40]
Flonk@home:~>echo 2 10 | codegolf
[0,3,4,5,10,11,12,13,14,21]
Flonk@home:~>echo 12 6 | codegolf
[2,4,5,6,9,10]
Flonk
quelle
4

Python 3, 590 639 Zeichen

from itertools import count as C
D=lambda n,t='1':bin(n).count(t)
Y=range
def O():
 for n in C(0):yield from bin(n)[2:]
def B():
 s=i=0
 while 1:
  i+=s
  for j in Y(i,i+s+1):yield j
  s+=2;i+=s-1
def s(i):return D(i)==1
def F():
 a=[1]*3
 for n in C(3):a+=[a[n-a[n-1]]+a[n-a[n-2]]];yield a[-1]
L,R=input().split()
J=[x for x,U in zip([F(),(n for n in C(0)if s(D(n,'0')-1)and s(D(n))),B(),(i for i,c in enumerate(O())if'1'>c)],"{0:04b}".format(int(L)))if U>'0']
X=[set()for _ in J]
M=[]
Z=int(R);K=1
while len(M)<Z:
 for x,j in zip(X,J):x.add(next(j))
 for _ in Y(K):X[0].add(next(J[0]));K+=1
 M=X[0]
 for x in X:M=M&x
print(sorted(M)[:Z])

Dies ist die einfache Lösung: Verwenden Sie Generatoren, um jede der unendlichen Sequenzen zu definieren, und fügen Sie jeder Sequenz einen Schritt hinzu, solange der Schnittpunkt nicht groß genug ist.

Um die nicht monoton ansteigende Hofstadter-Sequenz zu berücksichtigen: Bei jedem Schritt generiere ich doppelt so viele für diese Sequenz, z. B. 1, dann 2, 4, 8, 16, 32 usw. Ich denke, das erfüllt die in der Frage angegebene Grenze und es ist immer noch schnell genug für alle dort vorgestellten Testfälle.

Claudiu
quelle
2
Golf: from itertools import count as C-> from itertools import* C=count, def s(i):return D(i)==1-> s=lambda i:D(i)==1(Ich glaube nicht einmal, dass diese Funktion es kürzer macht ...), "{0:04b}".format(int(L)))if U>'0'->"{0:04b}".format(int(L)))if'0'<U
Justin
3

C #, 1923

Es wird wahrscheinlich nicht das kürzeste Programm sein, aber ich fand die Herausforderung interessant, also hier ist meine Lösung.

Das Ausführen aller 4 mit 35 Zahlen (15 35) dauert ungefähr 5 Sekunden.

Sie können es hier testen , aber beachten Sie, dass, wenn Sie OEIS4 möchten, die Anzahl der gewünschten Ziffern klein sein muss oder Netfiddle nicht mehr genügend Speicherplatz hat.

Golf gespielt

using System;using System.Collections;using System.Collections.Generic;using System.Linq;class p{public static void Main(string[] args){int b=0;IEnumerable<int>a=null;foreach(char c in Convert.ToString(int.Parse(args[0]),2).Reverse()){++b;if(c=='0')continue;switch(b){case 1: a=d(a,e());break;case 2: a=d(a,f());break;case 3: a=d(a,g());break;case 4: a=d(a,h(),true);break;}}if(a==null)return;bool j=true;foreach(int i in a.Take(int.Parse(args[1]))){if(j)j=false;else Console.Write(",");Console.Write(i);}}static IEnumerable<int>d(IEnumerable<int>k,IEnumerable<int>l,bool m=false){if(k==null)foreach(int n in l)yield return n;int o=0;int p=1;foreach(int i in k){Dictionary<int,HashSet<int>>q=m ? new Dictionary<int,HashSet<int>>(): null;int s=0;foreach(int n in l){if(!m){if(i<n)break;}else{if(!q.ContainsKey(o))q.Add(o,new HashSet<int>());q[o].Add(n);if(q.Count==1){int r=q[o].OrderBy(gi =>gi).Take(2).Sum();if(i<r)break;}else{int r=q[o].Concat(q[o-1]).OrderBy(gi =>gi).Take(2).Sum();if(i<r)break;}if(++s==p){o++;p=(int)Math.Pow(2,o);}}if(i==n){yield return i;break;}}}}static IEnumerable<int>e(){int t=0;for(int i=0;i<int.MaxValue;i++)foreach(char c in Convert.ToString(i,2)){if(c=='0')yield return t;t++;}}static IEnumerable<int>f(){int t=1;int u=0;bool v=true;using(IEnumerator<int>w=Enumerable.Range(0,int.MaxValue).GetEnumerator()){while(w.MoveNext()){if(v){if(u==0)u=t+1;yield return w.Current;if(--t==0)v=false;}else{if(t==0)t=u+1;if(--u==0)v=true;}}}}static IEnumerable<int>g(){for(int i=0;i<int.MaxValue;i++){string s=Convert.ToString(i,2);if(x(s.Count(c =>c=='0'))&& x(s.Count(c =>c=='1')))yield return i;}}static bool x(int y){return(y != 0)&&((y &(y-1))==0);}static IEnumerable<int>h(){return Enumerable.Range(1,int.MaxValue).Select(z);}static Dictionary<int,int>_=new Dictionary<int,int>();static int z(int n){int a;if(!_.TryGetValue(n,out a)){if(n<3)a=1;else a=z(n-z(n-1))+z(n-z(n-2));_.Add(n,a);}return a;}}

Lesbar

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

class Programm
{
    public static void Main(string[] args)
    {
        int index = 0;

        IEnumerable<int> intersection = null;

        foreach (char c in Convert.ToString(int.Parse(args[0]), 2).Reverse())
        {
            ++index;
            if (c == '0')
                continue;

            switch (index)
            {
                case 1: intersection = _join(intersection, OEIS1()); break;
                case 2: intersection = _join(intersection, OEIS2()); break;
                case 3: intersection = _join(intersection, OEIS3()); break;
                case 4: intersection = _join(intersection, OEIS4(), true); break;

                default: throw new ArgumentException();
            }
        }
        if (intersection == null)
            return;

        bool first = true;
        foreach (int i in intersection.Take(int.Parse(args[1])))
        {
            if (first) first = false;
            else Console.Write(",");

            Console.Write(i);
        }

        Console.ReadKey();
    }

    private static IEnumerable<int> _join(IEnumerable<int> intersection, IEnumerable<int> newSequence, bool hof = false)
    {
        if (intersection == null)
            foreach (int n in newSequence) yield return n;



        int generation = 0;
        int generationMax = 1;
        foreach (int i in intersection)
        {
            Dictionary<int, HashSet<int>> generationCache = hof ? new Dictionary<int, HashSet<int>>() : null;
            int count = 0;
            foreach (int n in newSequence)
            {
                if (!hof)
                {
                    if (i < n)
                        break;
                }
                else
                {
                    if (!generationCache.ContainsKey(generation))
                        generationCache.Add(generation, new HashSet<int>());

                    generationCache[generation].Add(n);

                    if (generationCache.Count == 1)
                    {
                        int lowerBound = generationCache[generation].OrderBy(gi => gi).Take(2).Sum();
                        if (i < lowerBound)
                            break;
                    }
                    else
                    {
                        int lowerBound = generationCache[generation].Concat(generationCache[generation - 1]).OrderBy(gi => gi).Take(2).Sum();
                        if (i < lowerBound)
                            break;
                    }

                    if (++count == generationMax)
                    {
                        generation++;
                        generationMax = (int)Math.Pow(2, generation);
                    }
                }

                if (i == n)
                {
                    yield return i;
                    break;
                }
            }
        }
    }


    static IEnumerable<int> OEIS1()
    {
        int position = 0;
        for (int i = 0; i < int.MaxValue; i++)
            foreach (char c in Convert.ToString(i, 2))
            {
                if (c == '0')
                    yield return position;
                position++;
            }
    }

    static IEnumerable<int> OEIS2()
    {
        int take = 1;
        int skip = 0;
        bool doTake = true;
        using (IEnumerator<int> enumerator = Enumerable.Range(0, int.MaxValue).GetEnumerator())
        {
            while (enumerator.MoveNext())
            {
                if (doTake)
                {
                    if (skip == 0)
                        skip = take + 1;
                    yield return enumerator.Current;
                    if (--take == 0)
                        doTake = false;
                }
                else
                {
                    if (take == 0)
                        take = skip + 1;
                    if (--skip == 0)
                        doTake = true;
                }
            }
        }
    }

    static IEnumerable<int> OEIS3()
    {
        for (int i = 0; i < int.MaxValue; i++)
        {
            string s = Convert.ToString(i, 2);
            if (_isPowerOfTwo(s.Count(c => c == '0')) && _isPowerOfTwo(s.Count(c => c == '1')))
                yield return i;
        }
    }

    static bool _isPowerOfTwo(int number)
    {
        return (number != 0) && ((number & (number - 1)) == 0);
    }

    static IEnumerable<int> OEIS4()
    {
        return Enumerable.Range(1, int.MaxValue).Select(HofstadterQ);
    }

    static Dictionary<int, int> _hofstadterQCache = new Dictionary<int, int>();

    static int HofstadterQ(int n)
    {
        int result;
        if (!_hofstadterQCache.TryGetValue(n, out result))
        {
            if (n < 3)
                result = 1;
            else
                result = HofstadterQ(n - HofstadterQ(n - 1)) + HofstadterQ(n - HofstadterQ(n - 2));

            _hofstadterQCache.Add(n, result);
        }
        return result;
    }
}

Erläuterung

Dies nutzt die Bigtime der faulen Auswertung, die es schnell macht, wenn ich glaube. Außerdem war ich faul, irgendein "Bitlogic" unter Verwendung der Convert.ToString-Methode (Nummer 2) des Frameworks zu machen. Dadurch wird jede Zahl in ihre Binray-Darstellung als Zeichenfolge umgewandelt.

Ich musste meine eigene Methode schreiben, um die Sequenzen zu schneiden, da die Linq-Methode den Schnittpunkt der vollständigen Sequenz berechnet, und das war buchstäblich unmöglich.

CSharpie
quelle