计算构成唯一集合的数组


11

这个问题具有类似的设置,以找到适合一组和的数组,尽管其目标完全不同。

考虑一个A长度数组n。该数组仅包含正整数。例如A = (1,1,2,2)。让我们将定义f(A)为的所有非空连续子数组之和的集合A。在这种情况下f(A) = {1,2,3,4,5,6}。产生步骤f(A) 如下:

的子阵列A(1), (1), (2), (2), (1,1), (1,2), (2,2), (1,1,2), (1,2,2), (1,1,2,2)。它们各自的总和为1,1,2,2,2,3,4,4,5,6。因此,您从此列表中获得的集合是{1,2,3,4,5,6}

如果没有其他相同长度的数组,则我们将数组称为A 唯一数组,除了反向数组。作为示例,但是没有其他长度数组会产生相同的和集。Bf(A) = f(B)Af((1,2,3)) = f((3,2,1)) = {1,2,3,5,6}3

我们将仅考虑元素为给定整数s或的数组s+1。例如,如果s=1数组仅包含12

任务

任务,对于给定ns是计算该长度的独特阵列的数量。您可以假设s介于1和之间9

您不应该算数组的倒数以及数组本身。

例子

s = 1答案永远是n+1

s = 2,从n = 1上往下数的答案是:

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

s = 8,从n = 1上往下数的答案是:

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

得分了

对于给定n的代码,您的代码应输出s1到的所有值的答案9。您的分数是n在一分钟内完成的最高分。

测试中

我将需要在ubuntu机器上运行您的代码,因此请尽可能详细地说明如何编译和运行您的代码。

排行榜

  • n = 24,安德斯·卡塞格(Anders Kaseorg)in Rust(34秒)
  • n = 16,乌鲁斯在清洁区(36秒)
  • JRowan在Common Lisp中的n = 14(49秒)

因此,如果s = 8,则其为8和9的所有可能组合的数组。
JRowan '18 -10-24

@JRowan不。您不计算与任何其他数组具有相同总和的那些数组。
Anush

对于这一部分,我有些困惑。我们将只考虑元素为给定整数s或s + 1的数组。例如,如果s = 1,则数组仅包含1和2。那么,如果n为2,而s为3,则要测试的数组是什么?
JRowan

怎么样[3,3]和即时通讯目前删除列表的相反,例如。[3,4]-> [4,3]
JRowan '18

2
@RosLuP首先,您打算将其发布到另一个问题上,其次,[ 3,5,4 ]是[ 3,5,1,4 ]的子集而不是子数组
安德斯·卡塞格

Answers:


5

,n≈24

需要每晚使用Rust才能获得便利的reverse_bits功能。rustc -O unique.rs用(例如)编译并运行./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.
}

很好,谢谢。它在大约90秒内完成n = 25。但是主要的问题是它占用了我8GB RAM的70%。
阿努什

我突然有点担心。你是否检查该阵列相对于与所有其它可能的阵列,或者只是阵列,价值观ss+1在其中?
阿努什

@Anush是的,我用一些内存使用量来换取速度。我正在计数具有值s和的其他数组s + 1所不具有的唯一数组(因为您说过这是我们将考虑的唯一数组),尽管这是否会有所作为尚不明显。
安德斯·卡塞格

1
我想我明天需要解决这个问题。数组1,1,2,2和1,1,1,3都给出总和1,2,3,4,5,6。但是前者在只有1和2的数组中并不是唯一的,因此如果现在有所作为,我会感到困惑。
阿努什

2
@Anush确实有所不同:[1、2、2、2]的和在长度为1和2的长度为4的数组中是唯一的,但等于[1、2、3、2]的和。
安德斯·卡塞格

2

普通Lisp SBCL,N = 14

呼叫功能(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)))))

这是运行时间

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)

我该如何运行?我是否将代码复制到文件中并sbcl以某种方式调用它?
Anush

1
我使用emacs和slime,但是您可以在目录调用中将其放入test.lisp文件和sbcl提示文件中(加载“ test.lisp”),然后调用该函数的底部方式
JRowan

2

清洁

当然,这不是最有效的方法,但是我很想知道一个简单的按值过滤器的性能如何。

也就是说,使用此方法仍需改进。

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

放置在名为的文件中main.icl,或将顶行更改为module <your_file_name_here>

用编译clm -h 1500m -s 50m -fusion -t -IL Dynamics -IL StdEnv -IL Platform main

您可以从标题中的链接获得TIO(和我自己)使用的版本,或者从此处获得更新的版本。


我认为这段代码无法提供正确的输出。我用s = 8尝试了一下,结果为[9,86,126,130,130,130,130,130,130]
Anush

@Anush嗯,我知道我已经测试过了。我将查看是否在那和发布的内容之间进行了任何更改,请给我几个小时,我可以在休息时进行。
世纪

@Anush为什么提供s?在问题中指出“ 对于给定的n,您的代码应输出s的所有值(从1到9)。”
世纪

1
我认为这就是您所说的“大脑冻结” :)我现在将计时您的代码。
Anush
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.