สลับดัชนีและค่า


29

งาน

เขียนโปรแกรมหรือฟังก์ชั่นซึ่งอินพุตเป็นรายการ / อาร์เรย์Xของจำนวนเต็มและเอาต์พุตเป็นรายการชุดของจำนวนเต็มYเช่นนั้นสำหรับแต่ละองค์ประกอบอีในแต่ละชุดY [ i ], X [ e ] = iและ ดังกล่าวว่าจำนวนขององค์ประกอบในชุดในYเท่ากับจำนวนขององค์ประกอบในX

(นี่เป็นการดำเนินการเดียวกับการย้อนกลับ hashtable / พจนานุกรมยกเว้นนำไปใช้กับอาร์เรย์แทน)

ตัวอย่าง

ตัวอย่างเหล่านี้ใช้การจัดทำดัชนีแบบ 1 แต่คุณสามารถใช้การจัดทำดัชนีแบบ 0 แทนหากคุณต้องการ

X             Y
[4]           [{},{},{},{1}]
[1,2,3]       [{1},{2},{3}]
[2,2,2]       [{},{1,2,3}]
[5,5,6,6]     [{},{},{},{},{1,2},{3,4}]
[6,6,5,5]     [{},{},{},{},{3,4},{1,2}]

ชี้แจง

  • คุณอาจแสดงชุดเป็นรายการหากคุณต้องการ หากคุณทำเช่นนั้นลำดับขององค์ประกอบจะไม่สำคัญ แต่คุณไม่สามารถทำซ้ำองค์ประกอบได้
  • คุณสามารถใช้รูปแบบ I / O ที่ไม่น่าสงสัยอย่างสมเหตุสมผล ตัวอย่างเช่นคุณสามารถแยกองค์ประกอบของชุดที่มีช่องว่างและชุดตัวเองด้วยการขึ้นบรรทัดใหม่
  • Yควรจะมีความยาวที่แน่นอนและอย่างน้อยก็นานพอที่จะมีองค์ประกอบทั้งหมดของXเป็นดัชนีอาร์เรย์ อย่างไรก็ตามอาจยาวกว่าองค์ประกอบสูงสุดของX (องค์ประกอบเพิ่มเติมจะเป็นชุดว่าง)
  • องค์ประกอบของXจะเป็นดัชนีอาร์เรย์ที่ถูกต้องเช่นจำนวนเต็มไม่เป็นลบหากคุณใช้การจัดทำดัชนีแบบ 0 หรือจำนวนเต็มบวกหากคุณใช้การจัดทำดัชนีแบบ 1

เงื่อนไขชัยชนะ

ในฐานะที่เป็นความท้าทายสั้นจะดีกว่า


ที่เกี่ยวข้อง ในโพสต์แซนด์บ็อกซ์ (ตอนนี้ถูกลบ แต่คุณสามารถดูได้ถ้าคุณมีชื่อเสียง) เราตัดสินใจว่ามันอาจจะไม่ซ้ำกัน แต่คุณสามารถลงคะแนนเพื่อปิดหากคุณไม่เห็นด้วย

"ลำดับขององค์ประกอบไม่สำคัญ" หมายความว่าผลลัพธ์ของ[5,5,6,6]และ[6,6,5,5]อาจเหมือนกันหรือไม่
Leun Nun

1
@LeakyNun ลำดับขององค์ประกอบของชุดในรายการผลลัพธ์ไม่สำคัญ ดังนั้น[5,5,6,6]และ[6,6,5,5]ไม่สามารถมีเอาต์พุตที่เหมือนกันได้ แต่ผลลัพธ์สำหรับ[5,5,6,6]อาจมีเช่น[{},{},{},{},{2,1},{4,3}]กัน
ngenisis

มีค่าสูงสุดที่คาดเดาได้ของดัชนีใน X หรือไม่? นอกจากนี้ชุดที่ว่างเปล่าสามารถมี 0 ในพวกเขาแทนที่จะเป็นที่ว่างเปล่าจริง ๆ ? ตัวอย่างเช่นจะ[{0},{0},{0},{0},{1,2},{3,4}]เป็นผลลัพธ์ที่ถูกต้องสำหรับ[5,5,6,6]?
Skidsdev

@Mayube: ไม่มีคำตอบแรก (แม้ว่าคุณจะใช้ภาษาที่มีช่วง จำกัด กับจำนวนเต็มคุณสามารถเขียนโปรแกรมราวกับว่าจำนวนเต็มอาจมีขนาดใหญ่มากและไม่ต้องกังวลว่ามันจะแตกถ้ามีคนให้คุณ - จำนวนเต็มของช่วงเป็นอินพุต) สำหรับคำถามที่สองนั่นคือไวยากรณ์ที่ไม่คลุมเครือ (ถ้าแปลก) เมื่อคุณใช้การจัดทำดัชนีแบบ 1 ดังนั้นใช่ในกรณีนั้น (ชัดเจนไม่ถ้าคุณกำลังใช้การจัดทำดัชนีแบบ 0 เพราะ 0 จะหมายถึง someting อื่น ๆ )

คำตอบ:


9

MATL , 8 ไบต์

tn:IXQ&D

อินพุตเป็นเวกเตอร์คอลัมน์โดยมี;ตัวคั่น (ตัวอย่าง[2;2;2]) เอาต์พุตคือการแทนค่าสตริงของอาร์เรย์เซลล์ของเวกเตอร์แถว (ตัวอย่าง{[]; [1 2 3]}) เวกเตอร์แถวขององค์ประกอบเดียวนั้นเหมือนกับตัวเลข (ดังนั้น{1; 2; 3}จะเป็นผลลัพธ์แทนที่จะเป็น{[1]; [2]; [3]})

ลองออนไลน์! หรือตรวจสอบกรณีทดสอบทั้งหมด

คำอธิบาย

t     % Implicit input, say x. Duplicate
n     % Number of elements, say N
:     % Range: [1 2 ... N]
IXQ   % accumarray(x, [1 2 ... N], [], @(x){sort(x).'})
&D    % String representation

งานส่วนใหญ่ทำโดยฟังก์ชันลำดับสูงกว่าของ Matlab accumarrayซึ่งจัดกลุ่มองค์ประกอบในอินพุตที่สองตามค่าการจับคู่ในครั้งแรกและใช้ฟังก์ชันที่ระบุกับแต่ละกลุ่ม ฟังก์ชั่นในกรณีนี้คือ@(x){sort(x).'}ผลลัพธ์ขององค์ประกอบที่เรียงลำดับในแต่ละกลุ่มและทำให้ผลลัพธ์สำหรับกลุ่มทั้งหมดจะถูกบรรจุในอาร์เรย์เซลล์




5

เยลลี่ขนาด 8 ไบต์

Jẋ"Ṭ€;"/

ลองออนไลน์!

มันทำงานอย่างไร

Jẋ"Ṭ€;"/  argument: z           eg. [6,6,4,4]
J         [1 .. len(z)]             [1,2,3,4]
   Ṭ€     untruth each of z         [[0,0,0,0,0,1],
                                     [0,0,0,0,0,1],
                                     [0,0,0,1],
                                     [0,0,0,1]]
 ẋ"       repeat each of ^^         [[[],[],[],[],[],[1]],
          as many times as           [[],[],[],[],[],[2]],
          each of ^                  [[],[],[],[3]],
                                     [[],[],[],[4]]]
       /  reduce by...
     ;"   vectorized concatenation  [[],[],[],[3,4],[],[1,2]]

4

Mathematica ขนาด 36 ไบต์

Join@@@#~Position~n~Table~{n,Max@#}&

คำอธิบาย

enter image description here

สำหรับแต่ละnใน{1, 2, ..., Max@#}ที่Max@#เป็นเลขที่ใหญ่ที่สุดในรายการป้อนข้อมูลคำนวณPositions ที่ปรากฏในรายการการป้อนข้อมูลn #ตั้งแต่Position[{6,6,5,5},5](ตัวอย่าง) ส่งคืน{{3},{4}}เราจึงApply Joinไปยังองค์ประกอบทั้งหมดที่ระดับ{1}ผลลัพธ์


3

Haskell , 45 ไบต์

s takes a list of integers and returns a list of lists. 1-indexed to keep the test case inputs unmodified (although the output gets some extra empty lists).

s l=[[i|(i,y)<-zip[1..]l,y==x]|x<-[1..sum l]]

Try it online!

These are pretty straightforward nested list comprehensions. The only slight tweak is taking advantage of the option to make a longer list by using sum instead of maximum.



3

R, 68 49 47 bytes

lapply(1:max(x<-scan()),function(y)which(y==x)) 

Surprisingly, a lot more straightforward than the longer solutions. Takes a vector x from STDIN, creates a vector from 1 to max(x), implicitly generates a list of length max(x), and checks which indices in x correspond with those in the new list. Implicitly prints output.

Older version:

o=vector('list',max(x<-scan()));for(i in x)o[[i]]=c(o[[i]],F<-F+1);o

Slightly different approach to the other R answer. Takes a vector to STDIN, creates a list with length equal to the maximum value in the input. Loops over the input and adds the index into the right place.

Uses 1-based indexing.



2

Jelly, 9 bytes

Ṭ+\ịĠȧ@"Ṭ

1-indexed, empty sets represented as 0, sets of one item represented as N sets of multiple items represented as [M,N,...]

Try it online!

How?

Ṭ+\ịĠȧ@"Ṭ - Main link: list a        e.g. [6,6,4,4]
Ṭ         - untruth a                     [0,0,0,1,0,1]
  \       - cumulative reduce with:
 +        -   addition                    [0,0,0,1,1,2]
    Ġ     - group indices of a by value   [[3,4],[1,2]]
   ị      - index into                    [[1,2],[1,2],[1,2],[3,4],[3,4],[1,2]]
        Ṭ - untruth a                     [0,0,0,1,0,1]
       "  - zip with:
     ȧ@   -   and with reversed @rguments [0,0,0,[3,4],0,[1,2]]

2

JavaScript (ES6), 64 62 bytes

Saved 2 bytes thanks to @SteveBennett


Takes 0-indexed input. Returns a comma-separated list of sets.

a=>a.map((n,i)=>o[n]=[i,...o[n]||[]],o=[])&&`{${o.join`},{`}}`

Test cases


Alternate version, 53 bytes

If a simplified output such as '||||3,2|1,0' is acceptable, we can just do:

a=>a.map((n,i)=>o[n]=[i,...o[n]||[]],o=[])&&o.join`|`

Wow. I'm so confused how `{${o.join`},{`}}` is legal ES2015.
Steve Bennett

@SteveBennett, it's a template literal. In older versions of JS it would be "{" + o.join("},{") + "}", if that makes it any clearer.
Shaggy

No, I know about those - it's the backquote after the word join that confuses me. Is that closing the string (in which case wtf) or is that how you escape a close brace?
Steve Bennett

Hmm, ok, so in this context join` is equivalent to join('. Had no idea you could do that.
Steve Bennett

Ah, now I see. It's a tagged template literal. Which you can abuse to save a couple of characters whenever calling a function that takes one string argument (and ignores others): array.join` `. Super confusing here because you're embedding that within a template string, and even more confusingly, the joining string is },{, which coincidentally looked like part of the template string...and is just weird and ugly anyway. :)
Steve Bennett


1

Mathematica 62 bytes

(Y={}~Table~Max@#;Y[[#[[j]]]]~AppendTo~j~Table~{j,Tr[1^#]};Y)&

I'll run it for you

(Y={}~Table~Max@#;Y[[#[[j]]]]~AppendTo~j~Table~{j,Tr[1^#]};Y)&[{4,5,2,3,3,8,6,3}]

{{}, {3}, {4, 5, 8}, {1}, {2}, {7}, {}, {6}}

Try it online (just paste the code with ctrl-v and press shift+enter)
don't forget to paste the input list at the end like in the example above


Welcome to PPCG! You can save a byte by using infix notation for AppendTo. Also, {j,1,Length[#1]} could just be {j,Length@#}, or even shorter, {j,Tr[1^#]}. Tr[1^#] is a pretty common trick to save a byte over using Length.
ngenisis

1

Perl 6,  36 32  29 bytes

->\a{map {a.grep(*==$_):k},1..a.max}

Try it

{map {.grep(*==$^a):k},1.. .max}

Try it

{map {.grep($^a):k},1.. .max}

Try it


Expanded:

{  # bare block lambda with implicit parameter 「$_」

  map

    {  # bare block lambda with placeholder parameter 「$a」

      .grep(  # grep for the values in 「$_」
        $^a   # that are equal to the currently tested value (and declare param)
      ) :k    # return the key (index) rather than the value
    },

    1 .. .max # Range from 1 to the maximum value in 「$_」

}

Returns zero based indexes, to get 1 based use cross operator (X) combined with + op. (33 bytes)

{1 X+.grep($^a):k}

To get it to return Sets just add set in there (total 37 bytes)

{set 1 X+.grep($^a):k}

1

R, 80 72 bytes

1-indexed, takes X from stdin. Returns a list of vectors of the indices, with NULL as the empty set.

X=scan();Y=vector('list',max(X));Y[X]=lapply(X,function(x)which(X==x));Y

Try it online!

old version:

X=scan();Y=vector('list',max(X));for(i in 1:length(X))Y[[X[i]]]=c(Y[[X[i]]],i);Y

Try it online!


I think that Y=list(); works just as well
rturnbull

Managed to shave off a few bytes in my answer :) codegolf.stackexchange.com/a/120024/59530
JAD




0

GNU Make, 214 213 208 204 bytes

X=$(MAKECMDGOALS)
M=0
P=$(eval N=$(word $1,$X))$(if $N,$(if $(shell dc -e$Nd$Mds.\>.p),$(eval M=$N),)$(eval A$N+=$1$(call $0,$(shell expr $1 + 1))),)
$(call P,1)$(foreach K,$(shell seq $M),$(info $(A$K)))

I/O: input array via arguments, output to stdout, one per line, separated by spaces.

$ make -f swap.mk 2 2 2

3 2 1
make: *** No rule to make target `2'.  Stop.

Explanation

X=$(MAKECMDGOALS)     # Input array
M=0                   # Max value encountered in X
P=$(eval
    N=$(word $1,$X))  # Get next word from X
  $(if $N,$(if $(shell dc -e$Nd$Mds.\>.p),
    $(eval M=$N),)    # Update M
    $(eval A$N+=$1    # Append index to a variable named after value
      $(call $0,      # Recurse (call returns empty string)
        $(shell expr $1 + 1))),)
$(call P,1)           # Initial call to P. 1 is the first index
$(foreach K,          # Print all values of A* variables
  $(shell seq $M),
  $(info $(A$K)))     # Uninitialized ones default to empty strings

The order of indices in sets is reversed because P calls itself recursively before updating A$2 (call executed in the evaluation of the right-hand side).


Does make have any way to do arithmetic itself? Calling into external programs to do it feels a bit like cheating, because you could probably put much more of the algorithm into those programs and end up with a shorter program.

@ais523 It has not. Previous version used bc and grep. I could also use test and $?. dc has a terser syntax, but frankly all of these feel the same.
eush77


0

k, 13 bytes

{(=x)@!1+|/x}

This is 0-indexed.

Try it online!

{           } /function(x)
 (=x)         /make a map/dictionary of values to their indices
         |/x  /get maximum value in x
      !1+     /make a range from 0 to the value, inclusive
     @        /get map value at each of the values in the range
              /    0N is given where there is no result
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.