OEIS A005434'ü hesapla


10

Görev, OEIS A005434'ü mümkün olan en kısa sürede hesaplamaktır .

İkili bir Suzunluk dizesi düşünün n. Dizine ekleyerek, ile arasında sırayla herkes için eşleşme 1olup olmadığını belirleyebiliriz . Örneğin,S[1..i+1]S[n-i..n]i0n-1

S = 01010

verir

[Y, N, Y, N, Y].

Bunun nedeni ise 0maçları 0, 01uymuyor 10, 010maçlar 010, 0101uymuyor 1010 ve nihayet 01010kendisini eşleşir.

Tüm olası farklı bit uzunluk dizgileri üzerinde yineleme yaparken s ve s'nin f(n)farklı dizilerinin sayısı olarak tanımlayın .YN2^nSn

Gözlemci, bu sorunun son zamanlardaki başka bir sorunun daha basit bir varyantı olduğunu fark edecektir . Ancak, akıllı hilelerin bunu daha hızlı ve daha kolay hale getirmesini bekliyorum.

Görev

nBaşlangıç ​​noktasını artırmak 1için kodunuzun çıktısı alınmalıdır n, f(n).

Örnek cevaplar

Çünkü n = 1..24, doğru cevaplar:

1, 2, 3, 4, 6, 8, 10, 13, 17, 21, 27, 30, 37, 47, 57, 62, 75, 87, 102, 116, 135, 155, 180, 194

puanlama

Kodunuzun n = 1her biri için cevap vermesini yinelemesi gerekir n. Tüm koşuyu zamanlayacağım ve iki dakika sonra öldüreceğim.

Puanınız no zaman aldığınız en yüksek puan .

Beraberlik durumunda, ilk cevap kazanır.

Kodum nerede test edilecek?

Kodunuzu bir Lubuntu konuk VM'sinde (Windows 7 sunucumda) Virtualbox altında çalıştıracağım .

Dizüstü bilgisayarımda 8GB RAM ve 2 çekirdekli ve 4 iş parçacıklı Intel i7 5600U@2.6 GHz (Broadwell) CPU var. Komut kümesi SSE4.2, AVX, AVX2, FMA3 ve TSX'i içerir.

Her dil için önde gelen girişler

  • n = 599 yılında Pas bu Anders Kaseorg.
  • n = 30 olarak C Güvenlik çok kötü ile. Cygwin'de yerel olarak çalıştırıldığında paralel sürüm 32'ye çıkar.

math.uni-bielefeld.de/~sillke/SEQUENCES/autocorrelation-range.c ( OEIS sayfasından bağlantılı) -O3 ile çalıştır, makinemde <.02 saniyede <.02 saniyede 100'e kadar hesaplayabilir
vroomfondel

@rogaos Ah canım. Soruyu silmeliyim ama zaten bir cevabı var.

Bence bu hala harika bir sorun - ama belki 1000'e kadar? Veya golf için yeterince hızlı bir programın cevaplarını sorun
vroomfondel

1
@rogaos Zor sınırı tamamen kaldırdım.

Yanıtlar:


4

Pas , n ≈ 660

use std::collections::HashMap;
use std::iter::once;
use std::rc::Rc;

type Memo = HashMap<(u32, u32, Rc<Vec<u32>>), u64>;

fn f(memo: &mut Memo, mut n: u32, p: u32, mut s: Rc<Vec<u32>>) -> u64 {
    debug_assert!(p != 0);
    let d = n / p;
    debug_assert!(d >= 1);
    let r = n - p * if d >= 2 { d - 1 } else { 1 };

    let k = s.binary_search(&(n - r + 1)).unwrap_or_else(|i| i);
    for &i in &s[..k] {
        if i % p != 0 {
            return 0;
        }
    }

    if d >= 3 {
        let o = n - (p + r);
        n = p + r;
        s = Rc::new(s[k..].iter().map(|i| i - o).collect());
    } else if n == p {
        return 1;
    } else if k != 0 {
        s = Rc::new(s[k..].to_vec());
    }

    let query = (n, p, s);
    if let Some(&c) = memo.get(&query) {
        return c;
    }
    let (n, p, s) = query;

    let t = Rc::new(s.iter().map(|i| i - p).collect::<Vec<_>>());
    let c = if d < 2 {
        (1..r + 1).map(|q| f(memo, r, q, t.clone())).sum()
    } else if r == p {
        (1..p + 1)
            .filter(|&q| p % q != 0 || q == p)
            .map(|q| f(memo, r, q, t.clone()))
            .sum()
    } else {
        let t = match t.binary_search(&p) {
            Ok(_) => t,
            Err(k) => {
                Rc::new(t[..k]
                            .iter()
                            .cloned()
                            .chain(once(p))
                            .chain(t[k..].iter().cloned())
                            .collect::<Vec<_>>())
            }
        };
        (1..t.first().unwrap() + 1)
            .filter(|&q| p % q != 0 || q == p)
            .map(|q| f(memo, r, q, t.clone()))
            .sum()
    };
    memo.insert((n, p, s), c);
    c
}

fn main() {
    let mut memo = HashMap::new();
    let s = Rc::new(Vec::new());
    for n in 1.. {
        println!("{} {}",
                 n,
                 (1..n + 1)
                     .map(|p| f(&mut memo, n, p, s.clone()))
                     .sum::<u64>());
    }
}

Çevrimiçi deneyin!

Nasıl çalışır

Bu, Leo Guibas, Tellerde dönemler” (1981) 'de verilen özyinelemeli yüklemin hatırlanmış bir uygulamasıdır . Fonksiyon f(memo, n, p, s), uzunluk nile en küçük periyot arasındaki korelasyon sayısını pve ayrıca setteki periyotların her birini bulur s.


Diğer ilgili soruna daha hızlı bir çözüm olup olmadığını merak etmenizi sağlar. Çok etkileyici!

İlginçtir ki bu tamamen hafıza sınırlıdır. ~ 500'e kadar hızlanır ve RAM bittiğinde aniden yavaşlar.

2

Meydan okumaya başlamak için basit bir kaba kuvvet araması:

#include <stdio.h>
#include <stdint.h>
#include <string.h>

typedef uint16_t u16;
typedef uint64_t u64;

static u64 map[1<<16];

int main(void)
{
    for (u64 n = 1;; ++n) {
        u64 result = 1;
        u64 mask = (1ul << n) - 1;
        memset(map, 0, sizeof(map));

        #pragma omp parallel
        #pragma omp for
        for (u64 x = 1ul << (n - 1); x < 1ul << n; ++x) {

            u64 r = 0;
            for (u64 i = 1; i < n; ++i)
                r |= (u64) (x >> i == (x & (mask >> i))) << i;
            if (!r)
                continue;

            u16 h = (u16) (r ^ r >> 13 ^ r >> 27);
            while (map[h] && map[h] != r)
                ++h;

            if (!map[h]) {
                #pragma omp critical
                if (!map[h]) {
                    map[h] = r;
                    ++result;
                }
            }
        }

        printf("%ld\n", result);
    }
}

İle derleyin clang -fopenmp -Weverything -O3 -march=native. Makinemde 2 dakikada n = 34'e ulaşıyor.

EDIT: kolay paralellik için bazı OMP yönergelerini serpiştirdi.


@Lembik SE silme gerekçeleri dışında iyi bir cevap var mı? Birinin (muhtemelen yorum yapan kişinin) bu algoritmayı bir cevap olarak göndermesini ve bu cevabı kabul etmesini beklememeniz gerekir mi?
Grimmy

Çok iyi bir noktaya

Ne yazık ki CPU'mda toplam iki çekirdek olduğu için sanal kodda gerçekten paralel kodunuzu test edemiyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.