Benzersiz kümeler oluşturan dizileri sayma


11

Bu soru, hedeflerinde oldukça farklı olmasına rağmen, bir miktar toplamına uyan bir dizi bulmak için benzer bir kuruluma sahiptir .

Bir Auzunluk dizisi düşünün n. Dizi yalnızca pozitif tamsayılar içerir. Örneğin A = (1,1,2,2). f(A)Boş olmayan bitişik alt dizilerin toplamları kümesi olarak tanımlayalım A. Bu durumda f(A) = {1,2,3,4,5,6}. Üretilecek adımlar f(A) aşağıdaki gibidir:

Alt dizileri Avardır (1), (1), (2), (2), (1,1), (1,2), (2,2), (1,1,2), (1,2,2), (1,1,2,2). Onların toplamları 1,1,2,2,2,3,4,4,5,6. Bu nedenle bu listeden aldığınız set {1,2,3,4,5,6}.

Tersine çevrilmiş dizi dışında aynı uzunlukta başka bir dizi yoksa A benzersiz bir dizi çağırırız . Örnek olarak, ancak aynı toplamları üreten başka bir uzunluk dizisi yoktur .Bf(A) = f(B)Af((1,2,3)) = f((3,2,1)) = {1,2,3,5,6}3

Yalnızca öğelerin belirli bir tamsayı sveya olduğu bir diziyi dikkate alacağız s+1. Örneğin eğer s=1diziler sadece içerecektir 1ve 2.

Görev

Görev, belirli bir nve sbu uzunluktaki benzersiz dizilerin sayısını saymaktır. Sen varsayabiliriz sarasındadır 1ve 9.

Bir dizinin tersini ve dizinin kendisini saymamalısınız.

Örnekler

s = 1, cevap her zaman n+1.

s = 2, yukarıdan gelen cevaplar n = 1:

2,3,6,10,20,32,52,86

s = 8, yukarıdan gelen cevaplar n = 1:

2,3,6,10,20,36,68,130

Puan

Belirli için n, kodunuz tüm değerleri için çıkış cevabı gerektiği sdan 1için 9. Puanınız bunun nbir dakika içinde tamamlandığı en yüksek değerdir .

Test yapmak

Kodunuzu ubuntu makinemde çalıştırmam gerekecek, bu nedenle kodunuzu nasıl derleyeceğiniz ve çalıştıracağınız için lütfen mümkün olduğunca ayrıntılı talimatlar ekleyin.

Liderler Sıralaması

  • n = 24 Anders Kaseorg tarafından Rust (34 saniye)
  • n = 16 Ourous in Clean tarafından (36 saniye)
  • n = 14 JRowan tarafından Common Lisp'de (49 saniye)

Eğer s = 8 ise, 8 ve 9'luk tüm olası kombinasyonlardan oluşan bir dizi ise, başka bir şey yok mu?
JRowan

@JRowan Hayır. Diğer dizilerle aynı toplamlara sahip dizileri saymazsınız.
Anush

Biraz kafam karıştı bu bölüm Sadece elemanların verilen s veya s + 1 tamsayısı olduğu dizileri ele alacağız. Örneğin, s = 1 ise diziler sadece 1 ve 2'yi içerecektir. Öyleyse, n 2 ve s 3 ise, test edilecek diziler ne olurdu?
JRowan

ne [3,3] ve im şu anda listelerin tersini kaldırma örn. [3,4] -> [4,3]
JRowan

2
@RosLuP İlk olarak, bunu diğer soruya göndermek istediniz ve ikincisi, [3, 5, 4] bir altkümedir, ancak [3, 5, 1, 4] bir alt dizisidir .
Anders Kaseorg

Yanıtlar:


5

Pas , n ≈ 24

Uygun reverse_bitsözellik için her gece Pas gerektirir . rustc -O unique.rs(Örn.) İle derleyin ve çalıştırın ./unique 24.

#![feature(reverse_bits)]
use std::{collections::HashMap, env, mem, process};

type T = u32;
const BITS: u32 = mem::size_of::<T>() as u32 * 8;

fn main() {
    let args = env::args().collect::<Vec<_>>();
    assert!(args.len() == 2);
    let n: u32 = args[1].parse().unwrap();
    assert!(n > 0);
    assert!(n <= BITS);
    let mut unique = (2..=9).map(|_| HashMap::new()).collect::<Vec<_>>();
    let mut sums = vec![0 as T; n as usize];
    for a in 0 as T..=!0 >> (BITS - n) {
        if a <= a.reverse_bits() >> (BITS - n) {
            for v in &mut sums {
                *v = 0;
            }
            for i in 0..n {
                let mut bit = 1;
                for j in i..n {
                    bit <<= a >> j & 1;
                    sums[(j - i) as usize] |= bit;
                }
            }
            for s in 2..=9 {
                let mut sums_s =
                    vec![0 as T; ((n + (n - 1) * s) / BITS + 1) as usize].into_boxed_slice();
                let mut pos = 0;
                let mut shift = 0;
                let mut lo = 0;
                let mut hi = 0;
                for &v in &sums {
                    lo |= v << shift;
                    if BITS - shift < n {
                        hi |= v >> (BITS - shift);
                    }
                    shift += s;
                    if shift >= BITS {
                        shift -= BITS;
                        sums_s[pos] = lo;
                        pos += 1;
                        lo = hi;
                        hi = 0;
                    }
                }
                if lo != 0 || hi != 0 {
                    sums_s[pos] = lo;
                    pos += 1;
                    if hi != 0 {
                        sums_s[pos] = hi;
                    }
                }
                unique[s as usize - 2]
                    .entry(sums_s)
                    .and_modify(|u| *u = false)
                    .or_insert(true);
            }
        }
    }
    let mut counts = vec![n + 1];
    counts.extend(
        unique
            .iter()
            .map(|m| m.values().map(|&u| u as T).sum::<T>())
            .collect::<Vec<_>>(),
    );
    println!("{:?}", counts);
    process::exit(0); // Avoid running destructors.
}

Harika, teşekkürler. N = 25 için yaklaşık 90 saniye içinde tamamlanır. Ancak asıl sorun, 8GB RAM'imin% 70'ini kullanması.
Anush

Aniden bir şey için endişelendim. Dizilerin diğer tüm olası dizilere göre benzersiz olup olmadığını mı yoksa yalnızca değerlere sahip sve dizilerindeki dizileri s+1mi kontrol ediyorsunuz?
Anush

@Anush Evet, hız için biraz bellek kullanımı yaptım. Değerleri olan diğer dizilerle benzersiz olan dizileri sayıyorum sve s + 1(bunların bunları dikkate alacağımız tek diziler olduğunu söylediğinizden beri), bunun bir fark yaratıp yaratmayacağı hemen belli olmasa da.
Anders Kaseorg

1
Sanırım bunu yarın halletmem gerekecek. 1,1,2,2 ve 1,1,1,3 dizilerinin toplamı 1,2,3,4,5,6 toplamını vermektedir. Ancak birincisi sadece 1 ve 2 ile diziler arasında benzersiz değil, bu yüzden şimdi bir fark yaratırsa biraz kafam karıştı.
Anush

2
@Anush Bir fark yaratır: [1, 2, 2, 2] toplamları, uzunluk 4 ve 1 olan diziler arasında benzersizdir, ancak [1, 1, 2, 3] toplamlarına eşittir.
Anders Kaseorg

2

Ortak Lisp SBCL, N = 14

çağrı fonksiyonu (goahead ns)

    (defun sub-lists(l m &optional(x 0)(y 0))
  (cond; ((and(= y (length l))(= x (length l)))nil)
        ((= y (length l))m)
        ((= x (length l))(sub-lists l m 0(1+ y)))
    (t (sub-lists l (cons(loop for a from x to (+ x y)

             when (and(nth (+ x y)l)(nth a l)(< (+ x y)(length l)))
                ;   while (nth a l)
             ;while(and(< (+ x y)(length l))(nth a l))
                    collect (nth a l))m) (1+ x)y))
    ))
(defun permutations(size elements)
  (if (zerop size)'(())
 (mapcan (lambda (p)
                    (map 'list (lambda (e)
                           (cons e p))
                         elements))
     (permutations (1- size) elements))))
(defun remove-reverse(l m)
  (cond ((endp l)m)
    ((member (reverse (first l))(rest l) :test #'equal)(remove-reverse (rest l)m))
    (t (remove-reverse (rest l)(cons (first l)m)))))
(defun main(n s)
  (let((l (remove-reverse (permutations n `(,s ,(1+ s)))nil)))

  (loop for x in l
     for j = (remove 'nil (sub-lists x nil))
       collect(sort (make-set(loop for y in j
        collect (apply '+ y))nil)#'<)
     )
  ))
(defun remove-dups(l m n)
  (cond ((endp l)n)
        ((member (first l) (rest l) :test #'equal)(remove-dups(rest l)(cons (first l) m) n))
    ((member (first l) m :test #'equal)(remove-dups(rest l)m n))
    (t(remove-dups (rest l) m (cons (first l) n))))

  )
(defun goahead(n s)
  (loop for a from 1 to s
  collect(length (remove-dups(main n a)nil nil))))
(defun make-set (L m)
  "Returns a set from a list. Duplicate elements are removed."
  (cond ((endp L) m)
    ((member (first L) (rest L)) (make-set (rest L)m))
    ( t (make-set (rest L)(cons (first l)m)))))

işte çalışma süreleri

CL-USER> (time (goahead 14 9))
Evaluation took:
  34.342 seconds of real time
  34.295000 seconds of total run time (34.103012 user, 0.191988 system)
  [ Run times consist of 0.263 seconds GC time, and 34.032 seconds non-GC time. ]
  99.86% CPU
  103,024,254,028 processor cycles
  1,473,099,744 bytes consed

(15 1047 4893 6864 7270 7324 7328 7328 7328)
CL-USER> (time (goahead 15 9))
Evaluation took:
  138.639 seconds of real time
  138.511089 seconds of total run time (137.923824 user, 0.587265 system)
  [ Run times consist of 0.630 seconds GC time, and 137.882 seconds non-GC time. ]
  99.91% CPU
  415,915,271,830 processor cycles
  3,453,394,576 bytes consed

(16 1502 8848 13336 14418 14578 14594 14594 14594)

Bunu nasıl çalıştırırım? Kodunuzu bir dosyaya kopyalayıp bir sbclşekilde çağırıyor muyum?
Anush

1
Emacs ve slime kullanıyorum ama bir dosyaya test.lisp ve sbcl isteminde dizin çağrınızda (load "test.lisp") koyabilir ve sonra altta nasıl var fonksiyonunu çağırabilirsiniz
JRowan

2

Temiz

Kesinlikle en etkili yaklaşım değil, ama saf bir değer filtresinin ne kadar iyi olduğunu görmekle ilgileniyorum.

Bununla birlikte, bu yöntem kullanılarak hala iyileştirilmesi gereken bir miktar var.

module main
import StdEnv, Data.List, System.CommandLine

f l = sort (nub [sum t \\ i <- inits l, t <- tails i])

Start w
	# ([_:args], w) = getCommandLine w
	= case map toInt args of
		[n] = map (flip countUniques n) [1..9]
		_ = abort "Wrong number of arguments!"

countUniques 1 n = inc n
countUniques s n = length uniques
where
	lists = [[s + ((i >> p) bitand 1) \\ p <- [0..dec n]] \\ i <- [0..2^n-1]]
	pairs = sortBy (\(a,_) (b,_) = a < b) (zip (map f lists, lists))
	groups = map (snd o unzip) (groupBy (\(a,_) (b,_) = a == b) pairs)
	uniques = filter (\section = case section of [a, b] = a == reverse b; [_] = True; _ = False) groups

Adlı bir dosyaya yerleştirin main.iclveya üst satırı olarak değiştirin module <your_file_name_here>.

İle derleyin clm -h 1500m -s 50m -fusion -t -IL Dynamics -IL StdEnv -IL Platform main.

Sen versiyon Tio olsun (ve ben) başlığı bağlantıyı veya bir daha yeni birinden kullanılması olabilir burada .


Bu kod doğru çıktı verir sanmıyorum. Ben s = 8 ile denedim ve verir [9,86,126,130,130,130,130,130,130]
Anush

@Anush hmm Test ettiğimi biliyorum. Gördüğüm kadarıyla bu mesaj arasında bir şey değiştirip değiştirmediğimi göreyim, bana birkaç saat verin ve bunu tatilimde yapabilirim.
Οurous

@Anush Neden veriyorsunuz s? " Belirli bir n için , kodunuz 1'den 9'a kadar olan tüm s değerlerinin yanıtını vermelidir."
Οurous

1
Bence bu benim için bir beyin donması diyorsunuz :) Şimdi kodunuzu zamanlayacağım.
Anush
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.