就地枚举每个相同编号的序列


27

给定一个严格的正整数列表,遍历每个不同的数字,并用新系列的连续索引(从零或一个开始)替换所有出现的数字。

例子

[][]/[]

[42][0]/[1]

[7,7,7][0,1,2]/[1,2,3]

[10,20,30][0,0,0]/[1,1,1]

[5,12,10,12,12,10][0,0,0,1,2,1]/[1,1,1,2,3,2]

[2,7,1,8,2,8,1,8,2,8][0,0,0,0,1,1,1,2,2,3]/[1,1,1,1,2,2,2,3,3,4]

[3,1,4,1,5,9,2,6,5,3,5,9][0,0,0,1,0,0,0,0,1,1,2,1]/[1,1,1,2,1,1,1,1,2,2,3,2]


2
那么基本上到目前为止,出现该序列的次数是多少?
Jo King

1
@JoKing是的,这是陈述它的另一种方式,但是“到目前为止”表示从零开始,而“直到并包括此”表示从一开始。我想保留选择。
亚当

Answers:


23

JavaScript(ES6),26个字节

1个索引。

a=>a.map(o=x=>o[x]=-~o[x])

在线尝试!

已评论

a =>                // a[] = input array
  a.map(o =         // assign the callback function of map() to the variable o, so that
                    // we have an object that can be used to store the counters
    x =>            // for each value x in a[]:
      o[x] = -~o[x] //   increment o[x] and yield the result
                    //   the '-~' syntax allows to go from undefined to 1
  )                 // end of map()

1
我不知道它是如何工作的,但是看起来确实很优雅。
阿达姆

我以前从未见过-~-这绝对是宝石。
DaveMongoose

另外,也可以用来a存储值,但是-/ ~索引是必需的,因此不保存任何字节。
user202729


1
@DaveMongoose -~其实是一种常用的替代品+1(因为它有不同的优先级)在许多语言
ASCII-仅

10

R,27个字节

function(x)ave(x,x,FUN=seq)

在线尝试!

说明:

ave(x,x,FUN=seq)x使用xas的值作为分组键将向量拆分为子向量。然后,seq为每个组调用函数,并将每个结果重新排列回原始组位置。

最好看一个例子:

x <- c(5,7,5,5,7,6)
ave(x, x, FUN=seq) # returns 1,1,2,3,2


 ┌───┬───┬───┬───┬───┐
 │ 57557 │
 └───┴───┴───┴───┴───┘            
   |   |   |    |  ||   ▼    ▼  |
 GROUP A : seq(c(5,5,5)) = c(1,2,3)
   |   |   |    |  ||   ▼    ▼  |
 ┌───┐ | ┌───┬───┐ |1|23|
 └───┘ | └───┴───┘ |
       ▼           ▼
 GROUP B : seq(c(7,7)) = c(1,2)
       |           |
       ▼           ▼
     ┌───┐       ┌───┐
     │ 1 │       │ 2 │
     └───┘       └───┘ 

   |   |   |   |   |
   ▼   ▼   ▼   ▼   ▼ 
 ┌───┬───┬───┬───┬───┐
 │ 11232 │
 └───┴───┴───┴───┴───┘  

注意 :

seq(y)1:length(y)如果y有has length(y) > 1,则函数返回一个序列,但1:y[1]如果y仅包含一个元素,则从中返回一个序列。
幸运的是,这不是问题,因为在这种情况下,R (抱怨很多警告)仅选择了第一个值,这恰好是我们想要的:)


2
辉煌!我会为此添加赏金。从未见过ave
朱塞佩

我很荣幸,非常感谢!:)
digEmAll

6

MATL,4个字节

&=Rs

此解决方案基于1

MATL Online上尝试一下!

说明

用途[1,2,3,2]作为例子

    # Implicitly grab the input array of length N
    #
    #   [1,2,3,2]
    #
&=  # Create an N x N boolean matrix by performing an element-wise comparison
    # between the original array and its transpose:
    #
    #     1 2 3 2
    #     -------
    # 1 | 1 0 0 0
    # 2 | 0 1 0 1
    # 3 | 0 0 1 0
    # 2 | 0 1 0 1
    #
R   # Take the upper-triangular portion of this matrix (sets below-diagonal to 0)
    #
    #   [1 0 0 0
    #    0 1 0 1
    #    0 0 1 0
    #    0 0 0 1]
    #
s   # Compute the sum down the columns
    #
    #   [1,1,1,2]
    #
    # Implicitly display the result

2
啊,我知道有个老问题让我想到了类似的东西,它的唯一性是便宜,而MATL解决方案却有一个不同之处!
朱塞佩

5

APL(Dyalog Unicode),7个字节

非常感谢H.PWiz,Adám和dzaima在调试和纠正此问题上所提供的所有帮助。

+/¨⊢=,\

在线尝试!

说明

10字节的非默认版本将更容易解释

{+/¨⍵=,\⍵}

{         } A user-defined function, a dfn
      ,\⍵  The list of prefixes of our input list 
           (⍵ more generally means the right argument of a dfn)
           \ is 'scan' which both gives us our prefixes 
           and applies ,/ over each prefix, which keeps each prefix as-is
    ⍵=     Checks each element of  against its corresponding prefix
           This checks each prefix for occurrences of the last element of that prefix
           This gives us several lists of 0s and 1s
 +/¨       This sums over each list of 0s and 1s to give us the enumeration we are looking for

默契版做三件事

  • 首先,它删除了use in 的实例,,\⍵因为,\right本身可以隐式地弄清楚它应该对正确的参数进行操作。
  • 其次,⍵=我们更换,它代表权的说法
  • 第三,既然我们没有显式参数(在本例中为),我们可以删除括号,{}因为默认函数不使用括号


5

J,7个字节

1#.]=]\

在线尝试!

1个索引。

说明:

]\ all the prefixes (filled with zeros, but there won't be any 0s in the input):
   ]\ 5 12 10 12 12 10
5  0  0  0  0  0
5 12  0  0  0  0
5 12 10  0  0  0
5 12 10 12  0  0
5 12 10 12 12  0
5 12 10 12 12 10

]= is each number from the input equal to the prefix:
   (]=]\) 5 12 10 12 12 10
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0
0 1 0 1 0 0
0 1 0 1 1 0
0 0 1 0 0 1

1#. sum each row:
   (1#.]=]\) 5 12 10 12 12 10
1 1 1 2 3 2

K(oK)11 10字节

-1个字节感谢ngn!

{+/'x=,\x}

在线尝试!


1
嘿,你是幸福的,我所做的数据严格正...
亚当

@Adám是的,否则我需要在前缀前加上:)
Galen Ivanov

1
在k中:='->=
ngn






2

R,41个字节

function(x)diag(diffinv(outer(x,x,"==")))

在线尝试!

奇怪的是,在R中返回从零开始的索引更短。


再次,朱塞佩(Giuseppe),您对R的超常知识打败了我。我有一个60字节的不错的巧妙方法,但是,还不够!
Sumner18

@ Sumner18无论如何张贴!我总是从别人的方法中学到很多东西,获得反馈是最快的学习方式!
朱塞佩

感谢您的鼓励!我已经张贴了我的文章,并且随时欢迎提出改进建议!
Sumner18

2

Ruby,35个字节

->a{f=Hash.new 0;a.map{|v|f[v]+=1}}

不幸的是,这很平凡-构建一个散列来存储到目前为止遇到的每个条目的总数。

不幸的是,其他一些有趣的选项还不够短:

->a{a.dup.map{a.count a.pop}.reverse}   # 37
->a{i=-1;a.map{|v|a[0..i+=1].count v}}  # 38

2

R62 43字节

x=z=scan();for(i in x)z[y]=1:sum(y<-x==i);z

通过使用Giuseppe,删除了-19和-19个字节,并对表进行了更改,仅对实现进行了少许更改

原版的

x=z=scan();for(i in names(r<-table(x)))z[which(x==i)]=1:r[i];z

我无法与Giuseppe的知识竞争,所以我提交的论文比他的论文更长,但是使用我的基本知识,我认为此解决方案相当巧妙。

r<-table(x) 计算每个数字出现的次数并将其存储在r中,以备将来参考

names() 获取表中每个唯一条目的值,然后使用for循环遍历这些名称。

其余部分检查哪些条目与迭代相等,并存储一系列值(从1到迭代的条目数)

在线尝试!


您可以删除which()以保存7个字节。
朱塞佩

您的使用1:r[i]给了我一个table()完全删除的想法:x=z=scan();for(i in x)z[y]=1:sum(y<-x==i);z是43个字节!这是一个不错的方法!
朱塞佩

看来我们俩人都无法与digEmAll的R知识竞争!
朱塞佩

我看到了,绝对感到震惊!
Sumner18

2

Haskell,44个字节

([]#)
x#(y:z)=sum[1|a<-x,a==y]:(y:x)#z
_#e=e

在线尝试!

说明

从左到右遍历列表x,最初保留访问元素的列表[]

对于每次y计数,列表中所有相等的元素x


1
更长一些,但也许仍然很有趣:(#(0*));(x:r)#g=g x:r# \y->0^abs(y-x)+g y;e#g=e 在线尝试!
Laikoni

@Laikoni:您甚至是怎么想出来的,应该完全发布!
ბიმო


2

Perl 6、15个字节

*>>.&{%.{$_}++}

在线尝试!

对于基于1的索引,您可以将移到++之前%

说明:

*>>.&{        }  # Map the input to
      %          # An anonymous hash
       .{$_}     # The current element indexed
            ++   # Incremented

2

Haskell47 46字节

(#(*0))
(x:r)#g=g x:r# \y->0^(y-x)^2+g y
e#g=e

在线尝试!

BMO的答案不同,后者的答案更长一些。(并请借用他们漂亮的测试服。)

这个想法是遍历输入列表,并通过更新函数来跟踪每个元素发生的次数g。取消高尔夫:

f (const 0)
f g (x:r) = g x : f (\ y -> if x==y then 1 + g y else g y) r
f g []    = []

出现了两个有趣的高尔夫机会。首先对于的初始值g,一个常量函数将忽略其参数,并返回0

const 0  -- the idiomatic way
(\_->0)  -- can be shorter if parenthesis are not needed
min 0    -- only works as inputs are guaranteed to be non-negative
(0*)     -- obvious in hindsight but took me a while to think of

其次过变量表达式xy它的产量1,如果x平等y0以其他方式:

if x==y then 1else 0  -- yes you don't need a space after the 1
fromEnum$x==y         -- works because Bool is an instance of Enum
sum[1|x==y]           -- uses that the sum of an empty list is zero
0^abs(x-y)            -- uses that 0^0=1 and 0^x=0 for any positive x
0^(x-y)^2             -- Thanks to  Christian Sievers!

可能还有更短的方法。有人知道吗?


1
您可以使用0^(x-y)^2
Christian Sievers


1

Ruby,34个字节

->a{r=[];a.map{|x|(r<<x).count x}}

在线尝试!


->a{i=-1;a.map{|v|a[0..i+=1].count v}}简直不敢尝试,也没有想到只是构建一个新的数组,哈哈。辛苦了
DaveMongoose

1

bash,37个 24个字节

f()(for x;{ r+=$[a[x]++]\ ;};echo $r)

蒂奥

如果有效,也有这种变化,这是DigitalTrauma建议的

for x;{ echo $[a[x]++];}

蒂奥



@DigitalTrauma,谢谢,但是我不知道它是否违反了规则。也因为它被要求更换名单,也许应该是这样的tio.run/...
纳乌艾尔乌Fouilleul

2
@NahuelFouilleul很好,也可以使用完整程序,这是输入/输出列表的有效方法(IMO)
仅ASCII格式的

1

Perl 5、11个字节

$_=$h{$_}++

蒂奥

评论后的解释

  • $_在输入(-p-n开关)上循环时,perl的特殊变量包含当前行
  • $h{$_}++自动绘制地图%h并创建带有键$_和增量的条目,并在增量之前给出值
  • 特殊变量由于-p开关而被打印,-l开关去除输入端的行尾并在输出端增加行尾

看起来很棒。介意解释吗?
阿达姆

@Adám,感谢您的反馈,确实完成了
Nahuel Fouilleul



1

附件,23字节

{`~&>Zip[_,_[0:#_::0]]}

在线尝试!

说明

{`~&>Zip[_,_[0:#_::0]]}
{                     }    _: input (e.g., [5, 12, 10, 12, 12, 10])
             0:#_          range from 0 to length of input (inclusive)
                           e.g., [0, 1, 2, 3, 4, 5, 6]
                 ::0       descending range down to 0 for each element
                           e.g., [[0], [1, 0], [2, 1, 0], [3, 2, 1, 0], [4, 3, 2, 1, 0], [5, 4, 3, 2, 1, 0], [6, 5, 4, 3, 2, 1, 0]]
           _[       ]      get input elements at those indices
                           e.g., [[5], [12, 5], [10, 12, 5], [12, 10, 12, 5], [12, 12, 10, 12, 5], [10, 12, 12, 10, 12, 5], [nil, 10, 12, 12, 10, 12, 5]]
     Zip[_,          ]     concatenate each value with this array
                           e.g., [[5, [5]], [12, [12, 5]], [10, [10, 12, 5]], [12, [12, 10, 12, 5]], [12, [12, 12, 10, 12, 5]], [10, [10, 12, 12, 10, 12, 5]]]
   &>                      using each sub-array spread as arguments...
 `~                            count frequency
                               e.g. [12, [12, 10, 12, 5]] = 12 ~ [12, 10, 12, 5] = 2

1

C(gcc)65 62字节

c,d;f(a,b)int*a;{for(;c=d=b--;a[b]=d)for(;c--;d-=a[c]!=a[b]);}

在线尝试!

-2个字节(仅ASCII)


这感觉太简单了,但是使用其他方法似乎再也不过了。



@仅ASCII这是一个有效的答案吗?没有标题,没有声明,虽然输出,但它是一个片段以及许多警告。
AZTECCO

@AZTECCO警告很好(忽略stderr),只要它可以接受即可。请注意,这一个函数声明,外加一些变量声明-您可以将其放在任何位置作为顶级表达式,并且可以很好地进行编译。一大堆c答案(以及那些用更少的严格语法语言)的一般,因为这是不好的代码风格bytesaves的相当多的警告
ASCII-仅

好的,我可以理解,但是仍然有些不适。如果我们想用不同的集合(大小)进行测试,就必须修改代码,即使在打印循环中,输入也应该只是集合,而不是它的大小。”给出严格的正整数列表... ”,所以我认为输入内容应该只是列表。
AZTECCO

@AZTECCO不确定此讨论是否应包含在此答案的注释中,但您可能需要看一下meta-特别是有关I / O答案格式的内容。
attinat

1

K(ngn / k),18个字节

(,/.!'#'=x)@<,/.=x

在线尝试!


旧方法

K(ngn / k)27 23 22字节

{x[,/.=x]:,/.!'#'=x;x}

在线尝试!


这不是很好...快速又肮脏的解决方案,我稍后会在有机会考虑更好的方法时进行完善

说明:

  • =x返回一个字典,其中键是x的项,值是它们的索引(3 1 4 5 9 2 6!(0 9;1 3;,2;4 8 10;5 11;,6;,7)
  • i: 将字典分配给 i
  • #:'计算每个键的值(3 1 4 5 9 2 6!2 2 1 3 2 1 1
  • !:'列举每个值(3 1 4 5 9 2 6!(0 1;0 1;,0;0 1 2;0 1;,0;,0)
  • ,/.:提取值并展平列表(0 1 0 1 0 0 1 2 0 1 0 0
  • x[,/.:i]: 从i提取索引,展平,并在这些索引处从右侧列表中分配每个值

烦人的是,列表已更新,但赋值返回了空值,因此我需要在分号(;x)之后返回列表

编辑:去除了多余的结肠

edit2:删除了不必要的分配


0

视网膜0.8.2,30字节

\b(\d+)\b(?<=(\b\1\b.*?)+)
$#2

在线尝试!链接包括测试用例。1个索引。说明:正则表达式的第一部分依次匹配列表中的每个整数。后向分组与该整数在该行上的每次出现匹配,直到当前整数为止。然后将整数替换为匹配数。


0

批处理,61字节

@setlocal
@for %%n in (%*)do @set/ac=c%%n+=1&call echo %%c%%

1个索引。由于变量替换发生在解析之前,因此该set/a命令最终通过将字母c与列表中的整数(数字变量在批处理中默认为零)级联来增加变量名。然后将结果复制到另一个整数以便于输出(更精确地说,它节省了一个字节)。



0

Japt,8个字节

£¯YÄ è¶X

在这里尝试

£¯YÄ è¶X
             :Implicit input of array U
£            :Map each X at 0-based index Y
 ¯           :  Slice U to index
  YÄ         :    Y+1
     è       :  Count the elements
      ¶X     :    Equal to X
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.