Imprime la intersección de secuencias

9

Secuencias

Se le da cuatro secuencias de números, numerados 1a través 4.

  1. OEIS La ubicación de 0's cuando los números naturales se enumeran en binario. Aquí hay un ejemplo de cómo calcular la secuencia:

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

    El inicio de la secuencia es así: 0, 3, 7, 8, 10, 14, 19, 20, 21, 23, 24, 27, 29, 31, 36, 37, 40, 45, 51, ...


  1. OEIS Esta secuencia incluye el primer número natural, omite los siguientes dos, luego incluye los siguientes tres, luego omite los siguientes cuatro y continúa.

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

  1. OEIS Enteros positivos donde tanto el número de 0's como el número de 1' s en la representación binaria del número son potencias de 2.

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

  1. OEIS La secuencia Q de Hofstadter .

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

    Poco se demuestra rigurosamente acerca de esta secuencia, pero existen muchos resultados empíricos. Uno es particularmente importante, y puede suponer que es válido para toda la serie:

    Este artículo observó que los elementos de la serie se pueden agrupar en generaciones. Si los numeramos comenzando en 1, entonces la generación k contiene exactamente 2 k elementos. La propiedad relevante es que todos los números de la generación k se obtienen sumando dos números de las generaciones k-1 y / o k-2 , pero nunca de generaciones anteriores. Puede usar esta observación (y solo esta) para poner un límite inferior en los elementos restantes de la secuencia.


Desafío

Su desafío es imprimir los primeros xnúmeros en la intersección de las secuencias de entrada dadas.

Entrada: dos números separados por un espacio en STDIN. El primer número es un número entero de 1al 15incluido donde cada bit corresponde a una secuencia. El bit más bajo corresponde a la secuencia 1y el más alto corresponde a la secuencia 4. El segundo es la cantidad de números x,, para generar STDIN.

Salida: los primeros xnúmeros que se cruzan con las secuencias de entrada dadas. Imprima los números STDOUTcon cualquier espacio en blanco o puntuación clara como delimitador (espacios, tabulaciones, líneas nuevas, comas, dos puntos, puntos, etc.).


Ejemplos

1. Imprima los primeros 3números que están en cada secuencia.

Entrada: 15 3

Salida: 10,23,40


2. Imprima los primeros 12números en el número de secuencias 1y 4.

Entrada: 9 12

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


3. Imprima los primeros 10números en secuencia 2.

Entrada: 2 10

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


4. Imprima los primeros 6números en secuencias 3y 4.

Entrada: 12 6

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


Detalles

  • Puede imprimir la salida a medida que avanza o todo de una vez al final.

¡Muchas gracias a todos los que ayudaron con esto en el chat! Esta pregunta se benefició enormemente de estar en la caja de arena .

hmatt1
fuente
@chilemagic: ¿Cómo se definen los "primeros números X" en una intersección? Si llevas ambas secuencias en el 12 5ejemplo hasta el mismo índice, entonces 10sí aparece antes 9en la intersección ... como, ¿cómo, al pasar por las secuencias, decidirías omitir el 9número 3 como una posible intersección? Como si el # 3 tuviera 7, entonces se le requeriría que lo omita ya que eso no aparece en el # 4
Claudiu
@Claudiu Sus números de salida siempre deben aumentar, y cada número solo aparecerá una vez en su salida.
hmatt1
¿Hay un límite máximo para x?
Ypnypn
@ypnypn no codifica un límite, pero si su algoritmo es muy lento o no termina para entradas muy grandes, está bien. Este es el código de golf, por lo que puede ser ineficiente para guardar bytes.
hmatt1

Respuestas:

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

Se desempeña razonablemente bien. Aquí hay un par de ejemplos de 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
fuente
4

Python 3, 590 639 caracteres

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

Esta es la solución directa: use generadores para definir cada una de las secuencias infinitas, y siempre que la intersección no sea lo suficientemente grande, agregue un paso a cada secuencia.

Para tener en cuenta la secuencia de Hofstadter que no aumenta monotónicamente: en cada paso genero el doble para esa secuencia, por ejemplo, 1, luego 2, 4, 8, 16, 32, etc. Creo que satisface el límite establecido en la pregunta , y todavía es lo suficientemente rápido para todos los casos de prueba presentados allí.

Claudiu
fuente
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(ni siquiera creo que esta función lo haga más corto ...), "{0:04b}".format(int(L)))if U>'0'->"{0:04b}".format(int(L)))if'0'<U
Justin
3

C #, 1923

Probablemente no sea el programa más corto, pero el desafío me pareció interesante, así que aquí está mi solución.

Ejecutar los 4 con 35 Números (15 35) lleva unos 5 segundos.

Puede probarlo aquí , pero tenga en cuenta que si desea OEIS4, la cantidad de dígitos que desea debe ser pequeña o netfiddle se queda sin memoria.

Golfed

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

Legible

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

Explicación

Esto hace uso de Bigtime de evaluación perezosa, lo que hace que sea bastante rápido. También fui flojo haciendo cualquier "bitlogic" usando el método Convert.ToString (número, 2) de frameworks. Esto convierte cualquier número en su representación binray como una cadena.

Tuve que escribir mi propio método para intersecar las secuencias, ya que la intersección del método Linq calcula la intersección de la secuencia completa, y eso era literalmente imposible.

CSharpie
fuente