Imprimer l'intersection des séquences

9

Les séquences

On vous donne quatre séquences de nombres, numérotées 1par 4.

  1. OEIS L'emplacement de 0's lorsque les nombres naturels sont répertoriés en binaire. Voici un exemple de calcul de la séquence:

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

    Le début de la séquence se déroule comme suit: 0, 3, 7, 8, 10, 14, 19, 20, 21, 23, 24, 27, 29, 31, 36, 37, 40, 45, 51, ...


  1. OEIS Cette séquence comprend le premier nombre naturel, saute les deux suivants, puis inclut les trois suivants, puis saute les quatre suivants et continue.

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

  1. OEIS Entiers positifs où à la fois le nombre de 0et le nombre de 1dans la représentation binaire du nombre sont des puissances de 2.

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

  1. OEIS Le Hofstadter Q séquence .

    a (1) = a (2) = 1;
    a (n) = a (na (n-1)) + a (na (n-2)) pour 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, ...
    

    On sait peu de choses sur cette séquence, mais de nombreux résultats empiriques existent. L'une est particulièrement importante et vous pouvez supposer qu'elle est valable pour toute la série:

    Cet article a observé que les éléments de la série peuvent être regroupés en générations. Si nous les numérotons à partir de 1, alors la k ème génération contient exactement 2 k éléments. La propriété pertinente est que tous les nombres de la génération k sont obtenus en additionnant deux nombres des générations k-1 et / ou k-2 , mais jamais des générations précédentes. Vous pouvez utiliser cette (et seulement cette) observation pour mettre une limite inférieure sur les éléments restants de la séquence.


Défi

Votre défi est d'imprimer les premiers xnombres à l'intersection des séquences d'entrée données.

Entrée: deux nombres séparés par un espace STDIN. Le premier nombre est un entier de 1à 15inclusif où chaque bit correspond à une séquence. Le bit le plus bas correspond à la séquence 1et le bit le plus élevé correspond à la séquence 4. La seconde est la quantité de nombres x, à afficher STDIN.

Sortie: Les premiers xnombres qui coupent les séquences d'entrée données. Imprimez les nombres STDOUTavec n'importe quel espace clair ou ponctuation comme délimiteur (espaces, tabulations, sauts de ligne, virgules, deux-points, points, etc.).


Exemples

1. Imprimez les premiers 3nombres de chaque séquence.

Contribution: 15 3

Production: 10,23,40


2. Imprimez les premiers 12chiffres du numéro de séquence 1et 4.

Contribution: 9 12

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


3. Imprimez les premiers 10nombres dans l'ordre2 .

Contribution: 2 10

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


4. Imprimez les premiers 6nombres dans les séquences 3et 4.

Contribution: 12 6

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


Détails

  • Vous pouvez imprimer la sortie au fur et à mesure ou à la fois à la fin.

Un grand merci à tous ceux qui ont aidé avec cela dans le chat! Cette question a grandement profité du fait d'être dans le bac à sable .

hmatt1
la source
@chilemagic: En fait, comment définissez-vous les "premiers nombres X" dans une intersection? Si vous prenez les deux séquences de l' 12 5exemple jusqu'au même index, 10cela vient en effet avant 9dans l'intersection ... comme, comment, en parcourant les séquences, décideriez-vous de sauter l' 9in # 3 comme intersection possible? Comme si # 3 avait 7dedans, alors vous seriez obligé de le sauter car cela n'apparaît pas dans # 4
Claudiu
@Claudiu Vos nombres sortis devraient toujours augmenter, et chaque nombre n'apparaîtrait qu'une seule fois dans votre sortie.
hmatt1
Y a-t-il une limite maximale à x?
Ypnypn
@ypnypn ne code pas une limite en dur, mais si votre algorithme est très lent ou ne se termine pas pour de très grandes entrées, c'est ok. Il s'agit de code golf, vous pouvez donc être inefficace pour économiser des octets.
hmatt1

Réponses:

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

Il fonctionne assez bien. Voici quelques exemples d'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
la source
4

Python 3, 590 639 caractères

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

C'est la solution simple: utilisez des générateurs pour définir chacune des séquences infinies, et tant que l'intersection n'est pas assez grande, ajoutez une étape à chaque séquence.

Pour tenir compte de la séquence de Hofstadter qui ne croît pas de manière monotone: à chaque étape, j'en génère deux fois plus pour cette séquence, par exemple 1, puis 2, 4, 8, 16, 32, etc. Je pense que cela satisfait la limite indiquée dans la question , et c'est toujours assez rapide pour tous les cas de test qui y sont présentés.

Claudiu
la source
2
Golfs: from itertools import count as C-> from itertools import* C=count, def s(i):return D(i)==1-> s=lambda i:D(i)==1(je ne pense même pas que cette fonction le raccourcisse ...), "{0:04b}".format(int(L)))if U>'0'->"{0:04b}".format(int(L)))if'0'<U
Justin
3

C #, 1923

Ce ne sera probablement pas le programme le plus court mais j'ai trouvé le défi intéressant, alors voici ma solution.

Exécuter les 4 avec 35 numéros (15 35) prend environ 5 secondes.

Vous pouvez le tester ici , mais notez que si vous voulez OEIS4, la quantité de chiffres que vous voulez doit être petite ou netfiddle manque de mémoire.

Golfé

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;}}

Lisible

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;
    }
}

Explication

Cela utilise bigtime d'évaluation paresseuse qui le rend très rapide i bellieve. De plus, j'étais paresseux à faire n'importe quel "bitlogic" en utilisant la méthode Convert.ToString (nombre, 2) des frameworks. Cela transforme n'importe quel nombre en sa représentation binray sous forme de chaîne.

J'ai dû écrire ma propre méthode pour intersecter les seuils car l'intersection Linq-Method calcule l'intersection de la séquence complète, et c'était littéralement impossible.

CSharpie
la source