在乘法表中对唯一数字进行排序


30

今天非常简单的挑战:

编写一个程序或函数,该程序或函数采用正整数N,并打印或返回出现在乘法表中的唯一数字的排序列表,该唯一的行和列被乘数均在1到N之间(含1和N)。

该列表可以按升序(最小到最大)或降序(最大到最小)排序,并且可以任何合理的格式输出。

以字节为单位的最短代码胜出!

当N = 4时,乘法表如下所示:

   1  2  3  4
  -----------
1| 1  2  3  4
 |
2| 2  4  6  8
 |
3| 3  6  9 12
 |
4| 4  8 12 16

表格中的唯一编号为1, 2, 3, 4, 6, 8, 9, 12, 16。这些已经排序,所以

1, 2, 3, 4, 6, 8, 9, 12, 16

可能是N = 4的确切输出。但是由于排序可以颠倒并且格式化还有一些余地,因此这些也是有效的输出:

[16,12,9,8,6,4,3,2,1]
1
2
3
4
6
8
9
12
16
16 12 9 8 4 3 2 1

测试用例

N=1 -> [1]
N=2 -> [1, 2, 4]
N=3 -> [1, 2, 3, 4, 6, 9]
N=4 -> [1, 2, 3, 4, 6, 8, 9, 12, 16]
N=5 -> [1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 20, 25]
N=6 -> [1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 30, 36]
N=7 -> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 25, 28, 30, 35, 36, 42, 49]
N=8 -> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 25, 28, 30, 32, 35, 36, 40, 42, 48, 49, 56, 64]
N=9 -> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 25, 27, 28, 30, 32, 35, 36, 40, 42, 45, 48, 49, 54, 56, 63, 64, 72, 81]
N=10 -> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 25, 27, 28, 30, 32, 35, 36, 40, 42, 45, 48, 49, 50, 54, 56, 60, 63, 64, 70, 72, 80, 81, 90, 100]
N=11 -> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25, 27, 28, 30, 32, 33, 35, 36, 40, 42, 44, 45, 48, 49, 50, 54, 55, 56, 60, 63, 64, 66, 70, 72, 77, 80, 81, 88, 90, 99, 100, 110, 121]
N=12 -> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25, 27, 28, 30, 32, 33, 35, 36, 40, 42, 44, 45, 48, 49, 50, 54, 55, 56, 60, 63, 64, 66, 70, 72, 77, 80, 81, 84, 88, 90, 96, 99, 100, 108, 110, 120, 121, 132, 144]

因此,基本上,代码会返回由N指定的乘法表中的数字列表,除非无法重复任何数字?
TanMath

N可以多大?
xsot

1
@xsot您可以假设N * N会小于您的语言的通常最大int值(可能是2 ^ 31-1)
卡尔文的爱好

因此从本质上讲这是1-n,n≤2的非素数。
gregsdennis 2015年

1
@gregsdennis不。没有很多复合材料。例如91,92,93,94,95,96为N = 10
卡尔文的嗜好

Answers:


12

Pyth,8个字节

S{*M^SQ2

在线尝试。

说明:SQ获取评估的列表输入(Q)并创建一个list [1, 2, ..., Q]^SQ2将列表本身的笛卡尔积与所有可能的乘积组合在一起。*M将所有这些对相乘以形成乘法表中的所有可能结果,并S{使它唯一并对其进行排序。


@FryAmTheEggman输入5已经需要排序,否则输出中的10和9会混乱。
Reto Koradi 2015年

该死的继续忘了M。+1
Maltysen

13

Python 2,61 51字节

lambda n:sorted({~(i%n)*~(i/n)for i in range(n*n)})

感谢xnor缩短了一些语法。


1
set(...)可以只是一组比较{...}。此外,此处默认情况下允许使用函数,因此您只需编写即可lambda n:...
xnor

感谢您提醒我有关集合理解的知识,我完全忘记了它的存在。
xsot

我看不到更好的方式来做到这一点,最好的,我递归看到的是56: f=lambda n:n*[0]and sorted(set(range(n,n*n+n,n)+f(n-1)))
xnor

11

APL,18 16字节

{y[⍋y←∪,∘.×⍨⍳⍵]}

这是一个未命名的单子函数。输出按升序排列。

说明:

             ⍳⍵]}   ⍝ Get the integers from 1 to the input
         ∘.×⍨       ⍝ Compute the outer product of this with itself
        ,           ⍝ Flatten into an array
       ∪            ⍝ Select unique elements
     y←             ⍝ Assign to y
 {y[⍋               ⍝ Sort ascending

解决了一个问题,并感谢Thomas Kwa节省了2个字节!


7

CJam,14 12个字节

@aditsu提出的改进的最新版本:

{)2m*::*0^$}

这是一个匿名函数。在线进行尝试,并提供测试所需的输入/输出代码。

@Martin提出了另一个{,:)_ff*:|$}同样长度的非常优雅的解决方案()。我使用了aittsu的那个,因为它与我的原始解决方案非常相似。

与原始解决方案的主要区别在于0,它将值保留在原始序列中,该序列在开始时节省了2个字节。您可能认为这无济于事,因为您必须0从结果中删除该值。但是@aditsu的想法的核心是0^末尾,这与有所不同0。这将删除0和,同时,由于它是设置操作,因此从解决方案集中消除了重复的元素。由于之前我已经需要2个字节来消除重复项,因此删除0基本上是免费的。

说明:

{     Start anonymous function.
  )     Increment to get N+1.
  2m*   Cartesian power, to get all pairs of numbers in range [0, N].
  ::*   Reduce all pairs with multiplication.
  0^    Remove 0, and remove duplicates at the same time since this is a set operation.
  $     Sort the list.
}     End anonymous function.

对于相同的长度,{2m*::)::*_&$}{)2m*::*_&$0-}
彼得·泰勒

2
如何少两个字节呢:){,:)_ff*:|$}
Martin Ender

1
另一种方式:{)2m*::*0^$}
–aditsu


4

朱莉娅,24个字节

n->sort(∪((x=1:n)*x'))

这是一个接受整数并返回整数数组的匿名函数。

取消高尔夫:

function f(n::Integer)
    # Construct a UnitRange from 1 to the input
    x = 1:n

    # Compute the outer product of x with itself
    o = x * transpose(x)

    # Get the unique elements, implicitly flattening
    # columnwise into an array
    u = unique(o)

    # Return the sorted output
    return sort(u)
end


4

zsh,86 56字节

感谢@Dennis节省了30(!)个字节

(for a in {1..$1};for b in {1..$1};echo $[a*b])|sort -nu

说明/不公开:

(                      # begin subshell
  for a in {1..$1}     # loop through every pair of multiplicands
    for b in {1..$1}
      echo $[a*b]      # calculate a * b, output to stdout
) | sort -nu           # pipe output of subshell to `sort -nu', sorting
                       # numerically (-n) and removing duplicates (-u for uniq)

这在Bash中不起作用,因为Bash不会扩展{1..$1}-它只是按字面意义进行解释(因此,用a=5; echo {1..$a}输出{1..5}代替1 2 3 4 5)。


我在等* sh答案。:D
艾迪生·克伦普

1
相关的打击技巧。似乎也适用于Z壳。
丹尼斯


4

Ruby,50个48字节

->n{c=*r=1..n;r.map{|i|c|=r.map{|j|i*j}};c.sort}

取消高尔夫:

->n {
  c=*r=1..n
  r.map { |i| c|=r.map{|j|i*j} }
  c.sort
}

使用嵌套循环将每个数字与每个其他数字相乘直到n,然后对数组进行排序。

50字节

->n{r=1..n;r.flat_map{|i|r.map{|j|i*j}}.uniq.sort}

用法:

->n{c=*r=1..n;r.map{|i|c|=r.map{|j|i*j}};c.sort}[4]
=> [1, 2, 3, 4, 6, 8, 9, 12, 16]

3

R,39个字节

cat(unique(sort(outer(n<-1:scan(),n))))

这将从STDIN读取一个整数并将一个空格分隔的列表写入STDOUT。

我们使用来创建乘法表作为矩阵,使用outer隐式展平为向量并使用进行排序,使用来sort选择唯一元素unique,并使用来分隔打印空间cat




2

K,17个字节

t@<t:?,/t*\:t:1+!

这里没有太多要说的。对(t@<t:)乘以笛卡尔自乘积()乘以()的唯一项(?)进行排序,/t*\:t:最大为N(1+!)。

实际上:

  t@<t:?,/t*\:t:1+!5
1 2 3 4 5 6 8 9 10 12 15 16 20 25

2

Haskell,55 54字节

import Data.List
f n=sort$nub[x*y|x<-[1..n],y<-[1..x]]

用法示例:f 4->[1,2,3,4,6,8,9,12,16]

nub 从列表中删除重复的元素。

编辑:@Zgarb发现了多余的$


2

J,21 20字节

感谢@Zgarb -1个字节!

/:~@~.@,@(1*/~@:+i.)

我的第一个J答案!如果有打高尔夫球的知识,请打高尔夫球。

这是一元函数。我们通过将列表1..input与其自身相乘,展平,采用唯一元素并进行排序来获取外部乘积。


2

Kotlin,70个字节

val a={i:Int->(1..i).flatMap{(1..i).map{j->it*j}}.distinct().sorted()}

非高尔夫版本:

val a: (Int) -> List<Int> = { 
    i -> (1..i).flatMap{ j -> (1..i).map{ k -> j * k } }.distinct().sorted()
}

用以下方法进行测试:

fun main(args: Array<String>) {
    for(i in 1..12) {
        println(a(i))
    }
}

2

壳牌+通用工具41

seq -f"seq -f%g*%%g $1" $1|sh|bc|sort -nu

或者:

Bash + coreutils,48岁

eval printf '%s\\n' \$[{1..$1}*{1..$1}]|sort -nu

在算术扩展内构造一个括号扩展:

\$[{1..n}*{1..n}]扩展为算术扩展$[1*1] $[1*2] ... $[1*n] ... $[n*n],将其求值并传递给printf,每行打印一个,管道传递给sort

谨慎使用引号,转义符并eval确保按要求的顺序进行扩展。


或者:

纯重打击(60)

eval a=($(eval echo [\$[{1..$1}*{1..$1}\]]=1))
echo ${!a[@]}


1

Minkolang 0.1425 22 18字节

我记得在发布此问题之前,我非常方便地实现了笛卡尔积!

1nLI20P[x*1R]sS$N.

在这里尝试。(输出顺序相反。)

说明

1                     Push a 1 onto the stack
 n                    Take number from input (n)
  L                   Pushes 1,2,...,n onto the stack
   I                  Pushes length of stack so 0P knows how many items to pop
    2                 Pushes 2 (the number of repeats)
     0P               Essentially does itertools.product(range(1,n+1), 2)
       [              Open for loop that repeats n^2 times (0P puts this on the stack)
        x             Dump (I know each product has exactly two numbers
         *            Multiply
          1R          Rotate 1 step to the right
            ]         Close for loop
             s        Sort
              S       Remove duplicates ("set")
               $N.    Output whole stack as numbers and stop.

1

JavaScript(ES6),92个 90字节

n=>eval(`for(r=[],a=n;a;a--)for(b=n;b;)~r.indexOf(x=a*b--)||r.push(x);r.sort((a,b)=>a-b)`)

说明

n=>eval(`                 // use eval to remove need for return keyword
  for(r=[],a=n;a;a--)     // iterate for each number a
    for(b=n;b;)           // iterate for each number b
      ~r.indexOf(x=a*b--) // check if it is already in the list, x = value
      ||r.push(x);        // add the result
  r.sort((a,b)=>a-b)      // sort the results by ascending value
                          // implicit: return r
`)

测试

N = <input type="number" oninput="result.innerHTML=(

n=>eval(`for(r=[],a=n;a;a--)for(b=n;b;)~r.indexOf(x=a*b--)||r.push(x);r.sort((a,b)=>a-b)`)

)(+this.value)" /><pre id="result"></pre>


1

Perl 6,27个字节

{squish sort 1..$_ X*1..$_} # 27
{unique sort 1..$_ X*1..$_} # 27
{sort unique 1..$_ X*1..$_} # 27

用法示例:

say {squish sort 1..$_ X*1..$_}(3); # (1 2 3 4 6 9)␤

my $code = {squish sort 1..$_ X*1..$_}

for 1..100 -> \N { say $code(N) }

my &code = $code;

say code 4; # (1 2 3 4 6 8 9 12 16)␤

1

Haskell,51个字节

f n=[i|i<-[1..n*n],elem i[a*b|a<-[1..n],b<-[1..n]]]

很无聊。只需使用和在中将列表过滤到表单[1..n*n]的元素即可。使用给出相同的长度a*bab[1..n]filter

f n=filter(`elem`[a*b|a<-[1..n],b<-[1..n]])[1..n*n]

我试了一段时间来生成诸如concatMap或的更聪明的产品列表mapM,但结果却更长。对成员资格的更复杂的检查是在52个字节处进行的,比原来增加了1个字节,但也许可以缩短。

f n=[k|k<-[1..n*n],any(\a->k`mod`a<1&&k<=n*a)[1..n]]

您可以通过使用节省3个字节(*)<$>..<*>..这样
ბიმო

1

JAVA-86字节

Set a(int a){Set s=new TreeSet();for(;a>0;a--)for(int b=a;b>0;)s.add(a*b--);return s;}

不打高尔夫球

Set a(int a){
    Set s = new TreeSet();
    for (;a>0;a--){
        for(int b = a;b>0;){
            s.add(a*b--);
        }
    }
    return s;
}

1

Pyth,11个字节

S{sm*RdSdSQ

这类似于朱莉娅的答案。感谢@Maltysen


1

PHP,74,73 70字节

while($i++<$j=$n)while($j)$a[]=$i*$j--;$a=array_unique($a);sort($a);

print_r($a); // Not counted, but to verify the result

取消高尔夫:

while($i++<$j=$n)
    while($j)
        $a[]=$i*$j--;

以前:

while(($j=$i++)<$n)for(;$j++<$n;)$a[]=$i*$j;$a=array_unique($a);sort($a);

不能100%确定如何处理输出,但是$a包含具有相应数字的数组。$n是geven via的数字$_GET['n'],带有register_globals=1


1

TeaScript37个 35个字符;40字节

@Downgoat节省了2个字节

TeaScript是用于高尔夫的JavaScript。

(b+r(1,+x¬)ßam(z=>z*l±s`,`.u¡s»l-i)

在线尝试!

脱节和解释

(b+r(1,+x+1)m(#am(z=>z*l)))s(',').u()s(#l-i)
              // Implicit: x = input number
r(1,+x+1)     // Generate a range of integers from 1 to x.
m(#           // Map each item "l" in this range "a" to:
 am(z=>       //  a, with each item "z" mapped to
  z*l))       //   z * l.
(b+      )    // Parse this as a string by adding it to an empty string.
s(',')        // Split the string at commas, flattening the list.
.u()          // Take only the unique items from the result.
s(#l-i)       // Sort by subtraction; the default sort sorts 10, 12, 100, etc. before 2.
              // Implicit: output last expression

您可以使用它r代替A.r生成范围
Downgoat 2015年

确定这是35 个字节吗?我得到35个字符或40个字节。
manatwork 2015年

@manatwork这将是ISO / IEC_8859-1编码格式的 35个字节。但是我不确定TeaScript是否支持该编码,因此现在将其更改为40个字节。
ETHproductions's

0

C,96字节

i,a[1<<16];main(n){for(scanf("%d",&n);i<n*n;a[~(i%n)*~(i++/n)]="%d ");while(i)printf(a[i--],i);}

这将按降序打印数字。欢迎提出建议,因为这看起来远非最佳。


0

JavaScript(ES6),86个字节

n=>{n++;a=[];for(j=1;j<n;j++)for(i=1;i<n;i++)if(a.indexOf(i*j)<0)a.push(i*j);return a}

希望缩短它(也许会尝试嵌套循环)。


0

Perl 5,91个字节

for my $y (1 .. $ARGV[0]){
    map {$s{$n}++ unless($s{$n=$y*$_}) } ($y .. $ARGV[0])
}
print join(" ", sort {$a<=>$b} keys %s) . "\n";

通过在命令行上传递参数来运行。缺少一些带有限制和警告的声明。


0

Python,124102字节

n=input()
l=[1]
for i in range(1,n+1):
 for j in range(1,n+1):l.append(i*j)
print sorted(list(set(l)))

更多pythonic!


2
这实际上是123个字节,而不是124,但你可以通过每个缩进层只使用一个单一的空间,而不是4.节省几个字节
亚历A.

1
您还可以l.append(i*j)与if条件语句放在同一行。我认为最终总共是102个字节。
El'endia Starman

3
并使用+=代替append
Kartik

@ El'endiaStarman编辑,谢谢!
TanMath

1
一个相对较小的问题:list(set(l))不保证会被排序。
El'endia Starman

0

Perl 5,67位元组

for$i(1..($n=pop)){$a{$_*$i}++for 1..$n}map say,sort{$a<=>$b}keys%a
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.