同一番号の各シリーズをインプレースで列挙する


27

厳密に正の整数のリストが与えられた場合、各個別の番号を調べて、そのすべての出現を新しいシリーズの連続するインデックス(ゼロまたは1ベース)に置き換えます。

[][]/[]

[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
基本的に、これまでにシーケンスが表示された回数は?
ジョーキング

1
@JoKingはい、それは別の言い方ですが、「これまで」はゼロベースを意味し、「これまで」は1ベースを意味します。私は選択を続けたかった。
アダム

回答:


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値をxグループ化キーとして使用して、ベクトルをサブベクトルに分割します。次に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)case yhas length(y) > 1にシーケンスを返しますが、要素が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ソリューションには1つのキャラクターがあります!
ジュゼッペ

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

暗黙バージョンは3つのことを行います

  • まず、as で使用され,\⍵ているのインスタンスを削除します,\ている、右側の引数で動作することになっていることが暗黙のうちにわかります。
  • 第二に、のために⍵=、我々は交換する、右の引数を表しています、
  • 第三に、明示的な引数(この場合{}がないので、暗黙の関数はそれらを使用しないため、中括弧を削除できます。

5

AWK、14

  • @NahuelFouilleulのおかげで1バイト節約
{print++a[$1]}

オンラインでお試しください!

上記は1ベースのインデックス作成を行います。ゼロベースのインデックス作成を希望する場合、追加のバイト:

{print a[$1]++}

オンラインでお試しください!


1
2番目は{print++a[$1]}スペースなしで1バイトを節約できることに注意してください
Nahuel Fouilleul

@NahuelFouilleulありがとう!
デジタルトラウマ

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バイト

ngnのおかげで-1バイト!

{+/'x=,\x}

オンラインでお試しください!


1
へえ、あなたは私がデータを厳密に正にしたことを嬉しく思います…
アダム

@Adámはい、そうでない場合はプレフィックスをボックス化する必要があります:)
ガレンイワノフ

1
in k:='->=
ngn






2

R、41バイト

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

オンラインでお試しください!

奇妙なことに、ゼロから始まるインデックスを返すのはRの方が短いです。


再びジュゼッペ、Rの優れた知識が私を打ち負かしました。私は60バイトでかなり巧妙なメソッドを使用していましたが、残念ながら、それでは十分ではありませんでした!
Sumner18

とにかく@ Sumner18に投稿してください!私はいつも他の人のアプローチから多くを学びます、そしてフィードバックを得ることが最も早く学ぶ方法です!
ジュゼッペ

励ましてくれてありがとう!私は今私のものを投稿しました、そして常に改善のための提案を受け入れています!
Sumner18

2

ルビー、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

-19バイト、Giuseppeのおかげで、これとテーブルを削除し、実装にわずかな変更を加えただけです。

元の

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

私はジュゼッペの知識と競うことができないので、私の提出は彼よりも幾分長いですが、私の基本的な知識を使用して、この解決策はかなり独創的であると感じました。

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);z43バイトです!これは素晴らしいアプローチです!
ジュゼッペ

どちらも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 オンラインで試してみてください!
ライコニ

@ライコニ:どうやってそれを思いついたのですか、完全に投稿すべきです!
ბიმო



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 []    = []

2つの興味深いゴルフの機会が生まれました。最初にの初期値に対して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あり1x等しい場合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
クリスチャンシーバーズ



1

bash、37 24バイト

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

TIO

有効な場合、DigitalTraumaが示唆するように、このバリエーションもあります。

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

TIO


1
リストをコマンドライン引数として渡します-tio.run/##S0oszvj/Py2/SKHCuporNTkjX0ElOjG6IlZbO5ar9v///8b/…-24バイトのみ。
デジタルトラウマ

@DigitalTrauma、ありがとう。ただし、ルールに違反したかどうかはわかりません。また、リストを置き換えるように求められたため、おそらくtio.run/の
Nahuel Fouilleul

2
@NahuelFouilleul It's fine, full programs are allowed too, and that's a valid method of inputting/outputting a list (IMO)
ASCII-only

1

Perl 5, 11 bytes

$_=$h{$_}++

TIO

explanations following comment

  • $_ perl's special variable containing current line when looping over input (-p or -n switches)
  • $h{$_}++ autovivifies the map %h and creates an entry with key $_ and increments and gives the value before increment
  • the special variable is printed because of -p switch, -l switch removes end of line on input and adds end of line on output

That looks amazing. Care to explain?
Adám

@Adám, thank you for your feedback, sure, done
Nahuel Fouilleul

1

Pari/GP, 32 bytes

a->p=0;[polcoeff(p+=x^t,t)|t<-a]

The k-th element in the answer is the coefficient of the xak term in the polynomial i=1kxai.

Try it online!



1

Attache, 23 bytes

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

Try it online!

Explanation

{`~&>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 bytes

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

Try it online!

-2 bytes thanks to ASCII-only


This felt too straightforward, but I couldn't seem to get any shorter with a different approach.



@ASCII-only is this a valid answer? No header included, no declarations, it's a snippet plus many warnings although it outputs.
AZTECCO

@AZTECCO warnings are fine (stderr is ignored), as long as it does what it should it's acceptable. note that this is a function declaration, plus some variable declarations - you can put it anywhere as a top level expression and it will compile fine. a lot of c answers (and those in languages with less strict syntax) do generally have quite a few warnings because of bytesaves that aren't good code style
ASCII-only

Ok I can understand, but there's still something not right to me. If we want to test with a different set(in size) we have to modify the code, even in the print loop, plus the input should be just the set, not its size."Given a list of strictly positive integers..." so I think input should be just the list.
AZTECCO

@AZTECCO not sure if this discussion should belong in this answer's comments, but you might want to take a look at meta - specifically on I/O and answer formats.
attinat

1

K (ngn/k), 18 bytes

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

Try it online!


OLD APPROACH

K (ngn/k), 27 23 22 bytes

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

Try it online!


this is not pretty... quick and dirty solution, i will be refining this later when i get the chance to think of a better approach

explanation:

  • =x returns a dict where keys are items of x and values are their indices (3 1 4 5 9 2 6!(0 9;1 3;,2;4 8 10;5 11;,6;,7))
  • i: assign dict to i
  • #:' count values for each key (3 1 4 5 9 2 6!2 2 1 3 2 1 1)
  • !:' enumerate each value (3 1 4 5 9 2 6!(0 1;0 1;,0;0 1 2;0 1;,0;,0))
  • ,/.: extract values and flatten list (0 1 0 1 0 0 1 2 0 1 0 0)
  • x[,/.:i]: extract indices from i, flatten, and assign each value from the right-side list at these indices

annoyingly, the list is updated but a null value is returned by the assignment, so i need to return the list after the semicolon (;x)

edit: removed extraneous colons

edit2: removed unnecessary assignment


0

Retina 0.8.2, 30 bytes

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

Try it online! Link includes test cases. 1-indexed. Explanation: The first part of the regex matches each integer in the list in turn. The lookbehind's group matches each occurrence of that integer on that line up to and including the current integer. The integer is then substituted with the number of matches.


0

Batch, 61 bytes

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

1-indexed. Because variable substitution happens before parsing, the set/a command ends up incrementing the variable name given by concatenating the letter c with the integer from the list (numeric variables default to zero in Batch). The result is then copied to another integer for ease of output (more precisely, it saves a byte).



0

Japt, 8 bytes

£¯YÄ è¶X

Try it here

£¯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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.