การเปลี่ยนอาร์เรย์เหมือน 2048


80

สมมติว่าเราต้องการเปลี่ยนอาเรย์เหมือนทำในเกม 2048 : ถ้าเรามีสององค์ประกอบต่อเนื่องเท่ากันในอาเรย์ให้รวมมันเป็นสองเท่าขององค์ประกอบค่า Shift ต้องส่งคืนอาร์เรย์ใหม่โดยที่ทุกคู่ของอิลิเมนต์ที่เท่ากันติดต่อกันจะถูกแทนที่ด้วยผลรวมของพวกเขาและคู่ไม่ควรตัดกัน การเลื่อนจะดำเนินการเพียงครั้งเดียวดังนั้นเราจึงไม่จำเป็นต้องรวมค่าผลลัพธ์อีกครั้ง ขอให้สังเกตว่าถ้าเรามี 3 องค์ประกอบเท่ากับติดต่อกันเราจะต้องรวมคนขวาสุดดังนั้นสำหรับตัวอย่างเช่น[2, 2, 2]ควรจะเป็นไม่ได้[2, 4][4, 2]

งานคือการเขียนฟังก์ชั่นที่สั้นที่สุดซึ่งใช้เวลาอาร์เรย์และส่งกลับอาร์เรย์เลื่อน

คุณอาจคิดว่าจำนวนเต็มทั้งหมดจะเป็นค่าบวกอย่างเคร่งครัด

ตัวอย่าง:

[] -> []
[2, 2, 4, 4] -> [4, 8]
[2, 2, 2, 4, 4, 8] -> [2, 4, 8, 8]
[2, 2, 2, 2] -> [4, 4]
[4, 4, 2, 8, 8, 2] -> [8, 2, 16, 2]
[1024, 1024, 512, 512, 256, 256] -> [2048, 1024, 512]
[3, 3, 3, 1, 1, 7, 5, 5, 5, 5] -> [3, 6, 2, 7, 10, 10]

ฉันสนใจวิธีการแก้ปัญหาด้วยการลด :)


11
นี่เป็นความท้าทายครั้งแรกที่ดีมาก ยินดีต้อนรับสู่เว็บไซต์!
DJMcMayhem

1
อินพุตไม่จำเป็นต้องจัดเรียงและตัวเลขมีค่ามากกว่าศูนย์นั่นเป็นข้อ จำกัด เฉพาะสำหรับตัวเลข เราอาจให้ค่าที่ใหญ่ที่สุดในขอบเขต int32 มาตรฐานฉันคิดว่า อาเรย์ที่ว่างเปล่าให้ผลอาเรย์ที่ว่างเปล่า ขอบคุณสำหรับการเข้าร่วมขอบคุณ :)
greenwolf

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

1
@Titus "โปรดสังเกตว่าหากเรามีองค์ประกอบที่เท่ากัน 3 ลำดับติดต่อกันเราจะต้องรวมองค์ประกอบที่ถูกต้องเช่น [2, 2, 2] ควรกลายเป็น [2, 4] ไม่ใช่ [4, 2]"
Martin Ender

1
การพิจารณาคดีเกี่ยวกับอาร์เรย์ที่ว่างเปล่าเป็นโชคร้าย; มันมีคำตอบที่ไม่ถูกต้องรวมถึงของฉันเอง
Dennis

คำตอบ:



19

Haskell, 47 57 50 ไบต์

e#l|a:b<-l,e==a= -2*a:b|1<2=e:l
map abs.foldr(#)[]

ใช้reduce(หรือfoldที่เรียกว่าใน Haskell นี่เป็นครึ่งขวาfoldr) ตัวอย่างการใช้งาน: ->map abs.foldr(#)[] $ [2,2,2,4,4,8][2,4,8,8]

แก้ไข: +10 ไบต์เพื่อให้สามารถใช้งานกับอาร์เรย์ที่ไม่เรียงลำดับได้เช่นกัน หมายเลขที่ผสานจะถูกแทรกเป็นค่าลบเพื่อป้องกันการผสานที่สอง map absพวกเขาจะได้รับการแก้ไขโดยเป็นครั้งสุดท้าย


เคล็ดลับที่มีเชิงลบเป็นสิ่งที่ดีจริงๆ!
xnor

14

Brain-Flak , 158 96

{({}<>)<>}<>{(({}<>)<><(({})<<>({}<>)>)>)({}[{}]<(())>){((<{}{}>))}{}{{}(<({}{})>)}{}({}<>)<>}<>

ลองออนไลน์!

คำอธิบาย:

1 กลับรายการ (ย้ายทุกอย่างไปยังสแต็กอื่น แต่ไม่สำคัญ)

{({}<>)<>}<>
{        }   #keep moving numbers until you hit the 0s from an empty stack
 ({}<>)      #pop a number and push it on the other stack
       <>    #go back to the original stack
          <> #after everything has moved, switch stacks

2 ทำขั้นตอนที่ 3-6 จนกว่าจะไม่มีอะไรเหลืออยู่ในสแต็กนี้:

{                                                                                         }

3 ทำซ้ำองค์ประกอบสองอันดับแรก (2 3 -> 2 3 2 3)

(({}<>)<><(({})<<>({}<>)>)>)

(({}<>)<>                   #put the top number on the other stack and back on the very top
         <(({})             #put the next number on top after:
               <<>({}<>)>   #copying the original top number back to the first stack
                         )>)

4 ใส่ 1 ไว้ด้านบนถ้าสองอันดับแรกเท่ากันหรือมิฉะนั้นเป็น 0 (จาก wiki)

({}[{}]<(())>){((<{}{}>))}{}

5 ถ้าสองอันดับแรกมีค่าเท่ากัน (ไม่เป็นศูนย์ด้านบน) ให้เพิ่มอีกสองรายการถัดไปแล้วกดผลลัพธ์

{{}(<({}{})>)}{}
{            }   #skip this if there is a 0 on top
 {}              #pop the 1
   (<      >)    #push a 0 after:
     ({}{})      #pop 2 numbers, add them together and push them back on 
              {} #pop off the 0

6 ย้ายองค์ประกอบด้านบนไปที่สแต็กอื่น

({}<>)<>

7 สลับไปที่สแต็กอื่นและพิมพ์โดยปริยาย

<>

กรุณาเพิ่มเครื่องหมายจุลภาคหลังชื่อภาษามิฉะนั้นจะทำให้กระดานแต้มนำหลุด: P
ASCII- เท่านั้น

9

PHP, 116 ไบต์

<?$r=[];for($c=count($a=$_GET[a]);$c-=$x;)array_unshift($r,(1+($x=$a[--$c]==$a[$c-1]))*$a[$c]);echo json_encode($r);

หรือ

<?$r=[];for($c=count($a=$_GET[a]);$c--;)$r[]=$a[$c]==$a[$c-1]?2*$a[$c--]:$a[$c];echo json_encode(array_reverse($r));

-4 ไบต์หากเอาต์พุตสามารถเป็นอาร์เรย์print_rแทน 'json_encode`

176 Bytes เพื่อแก้ปัญหานี้ด้วย Regex

echo preg_replace_callback("#(\d+)(,\\1)+#",function($m){if(($c=substr_count($m[0],$m[1]))%2)$r=$m[1];$r.=str_repeat(",".$m[1]*2,$c/2);return trim($r,",");},join(",",$_GET[a]));

1
คุณไม่สามารถใช้การเรียงลำดับได้เนื่องจากผลลัพธ์จะไม่ถูกจัดเรียงเสมอ: [4, 4, 2, 8, 8, 2] -> [8, 2, 16, 2]
Crypto

@Crypto คุณถูกต้องหลังจากมีการเพิ่มกรณีทดสอบใหม่ ก่อนที่จะใช้การเรียงลำดับก็โอเค
JörgHülsermann

for($i=count($a=$argv);--$i;)$b[]=($a[$i]==$a[$i-1])?2*$a[$i--]:$a[$i];print_r(array_reverse($b));แนวคิดเดียวกัน แต่สั้นกว่า
Crypto

@Crypto ฉันไม่แน่ใจเกี่ยวกับการส่งออกเป็นตัวแทนสตริงหรืออาร์เรย์ สำหรับการทดสอบ[]ฉันต้องการ$r=[];ขอบคุณสำหรับความช่วยเหลือของคุณ
JörgHülsermann

9

GNU sed, 41 38 37

รวม +1 สำหรับ -r
-3 ด้วยDigital Trauma
-1 ด้วยseshoumara

:
s,(.*)(1+) \2\b,\1!\2\2!,
t
y,!, ,

อินพุตและเอาต์พุตคือสตริงที่คั่นด้วยช่องว่างในหน่วยเดียว ( อิงตามมตินี้ )

ลองออนไลน์!


ใช้y,!, ,เพื่อบันทึก 1 ไบต์
seshoumara

@seshoumara Duh ... ทำไมฉันไม่คิดอย่างนั้น ขอบคุณ!
Riley

8

เรติน่า 32

\d+
$*
r`\b\1 (1+)\b
$1$1
1+
$.&

rในบรรทัดที่ 3 เปิดใช้งานการจับคู่ regex จากขวาไปซ้าย และนี่หมายความว่าการ\1อ้างอิงจำเป็นต้องมาก่อน(1+)กลุ่มการดักจับที่อ้างอิง

ลองออนไลน์


ดี .. ตัวเลือกจากขวาไปซ้ายเพื่อจับคู่นั้นค่อนข้างมีประโยชน์! มันเป็นส่วนหนึ่งของ. Net regex หรือคุณลักษณะ Retina หรือไม่
Dada

ฉันเพิ่งจะโพสต์ของฉันที่ 26 โดยใช้ linefeed- splitเป็นรูปแบบอินพุต: retina.tryitonline.net/ …เงินออมหลักมาจากที่นั้นและใช้การทับศัพท์เพื่อกำจัดการทดแทนที่สอง
Martin Ender

@Dada มันเป็นคุณสมบัติ. NET (และมันถูกใช้ภายใต้ประทุนเพื่อเปิดใช้งาน lookbehinds ความยาวโดยพลการ) Retina ยังไม่มีคุณสมบัติ regex ที่ไม่ซ้ำกัน (แม้ว่าจะมีคุณสมบัติการแทนที่ที่เป็นเอกลักษณ์)
Martin Ender

1
@MartinEnder ตกลงขอบคุณ! .NET regex ยอดเยี่ยมมาก! รหัสอิจฉา perl เห็น
Dada

@MartinEnder ฉันแก้ปัญหาของคุณแตกต่างกันมากพอที่จะรับประกันคำตอบอื่น
Digital Trauma


8

Python ขนาด 61 ไบต์

def f(l):b=l[-2:-1]==l[-1:];return l and f(l[:~b])+[l[-1]<<b]

บูลีนbตรวจสอบว่าองค์ประกอบสองรายการสุดท้ายควรยุบลงหรือไม่โดยตรวจสอบว่าพวกเขาเท่าเทียมกันในแบบที่ปลอดภัยสำหรับรายการความยาว 1 หรือ 0 หรือไม่องค์ประกอบสุดท้ายหากต่อท้ายด้วยตัวคูณ1สำหรับเท่ากันหรือ2ไม่เท่ากัน มันผนวกเข้ากับผลลัพธ์แบบเรียกซ้ำในรายการที่มีองค์ประกอบหลายอย่างถูกตัดออกในตอนท้าย ขอบคุณเดนนิสสำหรับ 1 ไบต์!


[l[-1]<<b]บันทึกเป็นไบต์
Dennis

l[-2:-1]is[l[-2]]
mbomb007

2
ฉันต้องการมันสำหรับรายการขนาด 0 และ 1
xnor

7

Perl, 43 + 1 ( -p) = 44 ไบต์

Ton Hospel มีคำตอบ 41 ไบต์ลองดูสิ!

-4 ขอบคุณ @Ton Hospel!

แก้ไข : เพิ่ม\bเป็นโดยไม่ได้มันก็ล้มเหลวกับการป้อนข้อมูลเช่นที่การส่งออกจะได้รับ24 428

$_=reverse reverse=~s/(\b\d+) \1\b/$1*2/rge

ทำงานด้วยการ-pตั้งค่าสถานะ:

perl -pe '$_=reverse reverse=~s/(\b\d+) \1\b/$1*2/rge' <<< "2 2 2 4 4"


ฉันไม่เห็นวิธีอื่นนอกเหนือจากการใช้reverseสองครั้งถึงการพับครึ่งทางขวา (เช่นเดียวกับs/(\d+) \1/$1*2/geการพับด้านซ้ายเช่น2 2 2จะกลายเป็น4 2แทน2 4) ดังนั้น 14 ไบต์จึงหายไปด้วยreverse... ฉันยังคิดว่าจะต้องมีวิธีอื่น (ดีกว่า) (มันคือ Perl หลังจากทั้งหมด!) โปรดแจ้งให้เราทราบหากคุณพบ!


reverse reverseดูเหมือนจะยาวไปหน่อย ฉันไม่มีความเชี่ยวชาญใน Perl แต่มีวิธีที่คุณสามารถสร้างทางลัดไปยังreverse(ถ้าไม่มีอะไรใช้ [ab] ใช้eval)?
Cyoce

Nice sexeger แจ้งให้ทราบว่าคุณสามารถออกจาก($_)
Ton Hospel

@ ขอบคุณพระวรสาร แน่นอนเอกสารreverseดูเหมือนว่าreverseไม่สามารถเรียกได้โดยไม่ต้องโต้แย้ง (ตัวอย่างที่แสดงให้เห็นว่าสามารถ แต่มีเพียงต้นแบบเดียวเท่านั้นreverse LIST) ดังนั้นฉันลืมเกี่ยวกับ$_การเป็นอาร์กิวเมนต์เริ่มต้น;)
Dada

LISTสามารถว่างเปล่า ...
Ton Hospel

@TonHospel แน่นอน แต่โดยปกติเมื่อตัวดำเนินการใช้$_เป็นอาร์กิวเมนต์เริ่มต้น doc จะระบุต้นแบบที่ไม่มีพารามิเตอร์ (เช่นprintหรือlenght... ) หรืออาจเป็นเพียงความรู้สึกผิดที่ฉันมี
Dada

7

JavaScript (ES6), 68 ไบต์

f=a=>a.reduceRight((p,c)=>(t=p[0],p.splice(0,c==t,c==t?c+t:c),p),[])
    
console.log([
  [],
  [2, 2, 4, 4],
  [2, 2, 2, 4, 4, 8],
  [2, 2, 2, 2],
  [4, 4, 2, 8, 8, 2],
  [1024, 1024, 512, 512, 256, 256],
  [3, 3, 3, 1, 1, 7, 5, 5, 5, 5],
].map(f))


2
ไม่เลว แต่เป็นไปตามข้อมูลโค้ดที่ดำเนินการ: [1024, 1024, 512, 512, 256, 256]การแก้ไขเป็น[2048, 512, 1024]และไม่[2048, 1024, 512]... ?
WallyWest

7

Perl 5.10, 61 50 ไบต์ ( 49 + 1 สำหรับการตั้งค่าสถานะ)

ขอบคุณ Ton Hospelประหยัด 11 ไบต์!

โซลูชันที่ไม่ใช้ Regex พร้อม-aธง:

@a=($F[-1]-$b?$b:2*pop@F,@a)while$b=pop@F;say"@a"

ลองที่นี่!


วิธีทางเลือกที่ดี อาร์เรย์ที่น่าสงสารมักจะแพ้กับสตริงใน Perl ถึงกระนั้นคุณก็สามารถเข้าใกล้ได้มากขึ้นโดยการโค๊ดรหัสของคุณเป็น@a=($F[-1]-$b?$b:2*pop@F,@a)while$b=pop@F;say"@a"(50 bytes)
Ton Hospel

@ TonHospel แน่นอนฉันมักจะหลีกเลี่ยงการแก้ปัญหาตามสตริง (เพียงเพื่อแสดงให้เห็นว่า Perl สามารถทำมากกว่านั้น!) ฉันไม่เล่นเพื่อชนะต่อไป: D ขอบคุณสำหรับเคล็ดลับการเล่นกอล์ฟ!
Paul Picard

7

JavaScript (ES6), 68 65 58 57 65 64 ไบต์

บันทึกแล้ว 1 ไบต์ขอบคุณ @ l4m2

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

f=(a,l=[],m)=>(x=a.pop())*!m-l?f(a,x).concat(l):x?f(a,2*x,1):[l]

console.log(f([2, 2, 4, 4]));
console.log(f([2, 2, 2, 4, 4, 8]));
console.log(f([2, 2, 2, 2]));
console.log(f([4, 2, 2]));


1
ฉันกำลังจะแนะนำการแก้ไขที่คุณเพิ่งทำ :)
ETHproductions

a=>(a.reverse()+'').replace(/(.),\1/g,(c,i)=>i*2).split`,`.reverse()?
l4m2

@ l4m2 ใช้งานได้กับอินพุตหลักเดียว แต่จะล้มเหลว[1024, 1024, 512, 512, 256, 256](ฉันคิดว่ากรณีทดสอบนี้อาจถูกเพิ่มในภายหลัง)
Arnauld

@Arnauld เอาล่ะคุณก็ล้มเหลว ...
l4m2

f=(a,l=[],m)=>(x=a.pop())*!m-l?f(a,x).concat(l):x?f(a,2*x,1):[l]?
l4m2

6

05AB1E , 26 ไบต์

D¥__X¸«DgL*ê¥X¸«£vy2ôO})í˜

ลองออนไลน์!

ขั้นตอนทั่วไป

  1. ลดโดยการลบเพื่อค้นหาว่าองค์ประกอบต่อเนื่องแตกต่างกันอย่างไร
  2. ลดโดยการลบดัชนีของสถานที่เหล่านั้นเพื่อค้นหาความยาวขององค์ประกอบต่อเนื่อง
  3. แยกอินพุตเป็นส่วนของความยาวเหล่านั้น
  4. แยกชิ้นเป็นคู่
  5. รวมแต่ละคู่
  6. ย้อนกลับแต่ละอันรวม
  7. แผ่ไปยังรายการ 1 มิติ

5

Mathematica, 53 ไบต์

Join@@(Reverse[Plus@@@#~Partition~UpTo@2]&/@Split@#)&

การอธิบาย

Split@#

แยกอินพุตเป็นรายการย่อยซึ่งประกอบด้วยองค์ประกอบที่เหมือนกัน ie {2, 2, 2, 4, 8, 8}กลายเป็น{{2, 2, 2}, {4}, {8, 8}}จะกลายเป็น

#~Partition~UpTo@2

แต่ละพาร์ทิชันของรายการย่อยลงในพาร์ทิชันที่มีความยาวมากที่สุด 2. คือ{{2, 2, 2}, {4}, {8, 8}}จะกลายเป็น{{{2, 2}, {2}}, {{4}}, {{8, 8}}}จะกลายเป็น

Plus@@@

รวมแต่ละพาร์ติชัน ie {{{2, 2}, {2}}, {{4}}, {{8, 8}}}กลายเป็น{{4, 2}, {4}, {16}}จะกลายเป็น

Reverse

กลับผลลัพธ์เนื่องจากPartitionคำสั่งของ Mathematica เปลี่ยนจากซ้ายไปขวา แต่เราต้องการให้พาร์ติชั่นไปในทิศทางอื่น ie {{4, 2}, {4}, {16}}กลายเป็น{{2, 4}, {4}, {16}}จะกลายเป็น

Join@@

เรียบผลลัพธ์ คือจะกลายเป็น{{2, 4}, {4}, {16}}{2, 4, 4, 16}


สวัสดี JHM! ขอบคุณสำหรับคำตอบ. ฉันไม่เข้าใจ Mathematica เป็นอย่างดีดังนั้นคุณสามารถเพิ่มคำอธิบายเล็กน้อยเกี่ยวกับสิ่งที่เกิดขึ้นได้หรือไม่?
isaacg

Plus@@@คือTr/@และฉันคิดว่าคุณสามารถหลีกเลี่ยงวงเล็บและJoin@@ถ้าคุณใช้##&@@กับผลลัพธ์ของReverse(ยังไม่ได้ทดสอบมัน)
Martin Ender

5

Java 7, 133 ไบต์

Object f(java.util.ArrayList<Long>a){for(int i=a.size();i-->1;)if(a.get(i)==a.get(i-1)){a.remove(i--);a.set(i,a.get(i)*2);}return a;}

อินพุตเป็น ArrayList และเพิ่งวนซ้ำไปข้างหลังลบออกและเพิ่มเป็นสองเท่าเมื่อจำเป็น

Object f(java.util.ArrayList<Long>a){
    for(int i=a.size();i-->1;)
        if(a.get(i)==a.get(i-1)){
            a.remove(i--);
            a.set(i,a.get(i)*2);
        }
    return a;
}

คุณกำลังเปรียบเทียบอ้างอิงในบรรทัดที่Long 3 พิจารณา== a.get(i)-a.get(i-1)==0
Jakob

4

Perl, 37 ไบต์

รวมถึง +4 สำหรับ -0n

รันด้วยอินพุตเป็นบรรทัดแยกบน STDIN:

perl -M5.010 shift2048.pl
2
2
2
4
4
8
2
^D

shift2048.pl:

#!/usr/bin/perl -0n
s/\b(\d+
)(\1|)$//&&do$0|say$1+$2


4

PHP, 86 100 99 94 ไบต์

for($r=[];$v=+($p=array_pop)($a=&$argv);)array_unshift($r,end($a)-$v?$v:2*$p($a));print_r($r);

ต้องการ PHP 7.0; รับค่าจากอาร์กิวเมนต์บรรทัดคำสั่ง

ทำงานด้วย-nrหรือลองออนไลน์


2
[2, 2, 2] ส่งคืน [4,2] แทน [2,4]
Crypto

for($r=[];$v=($p=array_pop)($a=&$_GET[a]);)array_unshift($r,end($a)-$v?$v:2*$p($a));print_r($r);สั้นลง 1 ไบต์
JörgHülsermann

3

Julia 205 ไบต์

t(x)=Val{x}
s(x)=t(x)()
f^::t(1)=f
^{y}(f,::t(y))=x->f(((f^s(y-1))(x)))
g()=[]
g{a}(::t(a))=[a]
g{a}(::t(a),B...)=[a;g(B...)]
g{a}(::t(a),::t(a),B...)=[2a;g(B...)]
K(A)=g(s.(A)...)
H(A)=(K^s(length(A)))(A)

ฟังก์ชั่นที่จะเรียกคือ H

เช่น H([1,2,2,4,8,2,])

นี่ไม่ใช่วิธีที่สั้นที่สุดในการทำจูเลีย แต่มันเจ๋งมากฉันอยากจะแบ่งปันมันต่อไป

  • t(a) เป็นประเภทค่าที่แสดงถึงค่า (a)
  • s(a) เป็นตัวอย่างของประเภทค่านั้น
  • gเป็นฟังก์ชั่นที่ยื้อกับความแตกต่างของค่า (ใช้ชนิดของค่า) และหมายเลขของพารามิเตอร์ และนั่นก็เจ๋ง
  • Kเพียงแค่ห่อgให้

ส่วนที่เย็นเป็นพิเศษ:

f^::t(1)=f
^{y}(f,::t(y))=x->f(((f^s(y-1))(x)))

สิ่งนี้นิยาม^โอเปอเรเตอร์ที่จะใช้กับฟังก์ชั่น เพื่อให้K^s(2)(X)เป็นเช่นเดียวK(K(X)) จึงHเป็นเพียงการโทรKบนKพวงของครั้ง - ครั้งพอที่จะยุบแน่นอนกรณีใด ๆ ที่ซ้อนกัน

สามารถทำได้สั้นกว่านี้มาก แต่วิธีนี้สนุกมาก


3

PowerShell v2 +, 81 ไบต์

param($n)($b=$n[$n.count..0]-join','-replace'(\d+),\1','($1*2)'|iex)[$b.count..0]

จะเข้าเป็นอาร์เรย์อย่างชัดเจน$nฝืนมัน$n[$n.count..0], -joins องค์ประกอบด้วยกันด้วยเครื่องหมายจุลภาคแล้ว regex -replaceSA จับคู่คู่หลักที่มีองค์ประกอบแรก*2และรายล้อมไปใน parens ท่อที่เป็นผลลัพธ์ (ซึ่งสำหรับการป้อนข้อมูล@(2,2,4,4)จะมีลักษณะ(4*2),(2*2)) ไปเป็นiex(ย่อมาจากInvoke-Expressionและคล้ายกับeval) ซึ่งแปลงการคูณเป็นตัวเลขจริง เก็บอาร์เรย์ผลในการเข้า$b, สุนทรีย์ว่าใน parens ที่จะวางไว้ในท่อแล้วกลับด้วย$b [$b.count..0]ปล่อยให้อิลิเมนต์ที่เกิดขึ้นบนไพพ์ไลน์และเอาต์พุตเป็นค่าปริยาย


กรณีทดสอบ

NB -ใน PowerShell แนวคิดของ "การคืน" อาเรย์ที่ว่างเปล่านั้นไม่มีความหมาย - มันถูกแปลง$nullเป็นทันทีที่มันออกจากขอบเขต - และมันก็เท่ากับการคืนค่าอะไรซึ่งเป็นสิ่งที่ทำในตัวอย่างแรก (หลังจากข้อผิดพลาด verbose บางอย่างชั่วร้าย) นอกจากนี้ผลลัพธ์ที่นี่จะถูกคั่นด้วยช่องว่างเนื่องจากเป็นตัวคั่นเริ่มต้นสำหรับอาร์เรย์ที่เป็นสตริง

PS C:\Tools\Scripts\golfing> @(),@(2,2,4,4),@(2,2,2,4,4,8),@(2,2,2,2),@(4,4,2,8,8,2),@(1024,1024,512,512,256,256),@(3,3,3,1,1,7,5,5,5,5)|%{"$_ --> "+(.\2048-like-array-shift.ps1 $_)}
Invoke-Expression : Cannot bind argument to parameter 'Command' because it is an empty string.
At C:\Tools\Scripts\golfing\2048-like-array-shift.ps1:7 char:67
+   param($n)($b=$n[$n.count..0]-join','-replace'(\d+),\1','($1*2)'|iex)[$b.count. ...
+                                                                   ~~~
    + CategoryInfo          : InvalidData: (:String) [Invoke-Expression], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.InvokeExpressionCommand

Cannot index into a null array.
At C:\Tools\Scripts\golfing\2048-like-array-shift.ps1:7 char:13
+   param($n)($b=$n[$n.count..0]-join','-replace'(\d+),\1','($1*2)'|iex)[$b.count. ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

 --> 
2 2 4 4 --> 4 8
2 2 2 4 4 8 --> 2 4 8 8
2 2 2 2 --> 4 4
4 4 2 8 8 2 --> 8 2 16 2
1024 1024 512 512 256 256 --> 2048 1024 512
3 3 3 1 1 7 5 5 5 5 --> 3 6 2 7 10 10

3

Javascript - 103 ไบต์

v=a=>{l=a.length-1;for(i=0;i<l;i++)a[l-i]==a[l-1-i]?(a[l-i-1]=a[l-i]*2,a.splice(l-i,1)):a=a;return a}

บันทึกแล้ว 16 ไบต์ขอบคุณ @MayorMonty เคล็ดลับในหน้านี้
Alexis_A

มันใช้งานไม่ได้ ทดสอบกับอัตราผลตอบแทน[2,2,4,4] [2,2,4,4]
Conor O'Brien

1
ได้. โหนด v6.2.1
Conor O'Brien

ของฉันไม่ดี .. ฉันกำลังเรียกใช้ด้วยรหัส JS อื่นในไฟล์เดียวกันและตัวแปรทั่วโลกได้ผสมกัน
Alexis_A

3

Brain-Flakขนาด 60 ไบต์

{({}<>)<>}<>{(({}<>)<>[({})]){((<{}>))}{}{({}<>{})(<>)}{}}<>

ลองออนไลน์!

คำอธิบาย:

{({}<>)<>}<>   Reverse stack

{   While input exists
  (
    ({}<>)   Push copy of last element to the other stack
    <>[({})] And subtract a copy of the next element
  )   Push the difference
  {   If the difference is not 0
    ((<{}>)) Push two zeroes
  }{}  Pop a zero
  {   If the next element is not zero, i.e the identical element
    ({}<>{})  Add the element to the copy of the previous element
    (<>)      Push a zero
  }{}    Pop the zero
}<>  End loop and switch to output stack


2

Julia, 73 82 Bytes

f(l)=l==[]?[]:foldr((x,y)->y[]==x?vcat(2x,y[2:end]):vcat(x,y),[l[end]],l[1:end-1])

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

หากส่วนหัวของรายการปัจจุบันไม่เท่ากับองค์ประกอบถัดไปที่จะเติมหน้าให้เติมเพียงแค่เติม

อื่นเอาหัวของรายการ (ฟังดูโหดร้าย) และเสริมองค์ประกอบคูณ 2

ตัวอย่าง

f([3,3,3,1,1,7,5,5,5,5]) 
returns a new list:
[3,6,2,7,10,10]

2

แร็กเก็ต 166 ไบต์

(λ(l)(let g((l(reverse l))(o '()))(cond[(null? l)o][(=(length l)1)(cons(car l)o)]
[(=(car l)(second l))(g(drop l 2)(cons(* 2(car l))o))][(g(cdr l)(cons(car l)o))])))

Ungolfed:

(define f
  (λ (lst)
    (let loop ((lst (reverse lst)) 
               (nl '()))
      (cond                            ; conditions: 
        [(null? lst)                   ; original list empty, return new list;
               nl]
        [(= (length lst) 1)            ; single item left, add it to new list
              (cons (first lst) nl)]
        [(= (first lst) (second lst))  ; first & second items equal, add double to new list
              (loop (drop lst 2) 
                    (cons (* 2 (first lst)) nl))]
        [else                          ; else just move first item to new list
              (loop (drop lst 1) 
                    (cons (first lst) nl))]  
        ))))

การทดสอบ:

(f '[])
(f '[2 2 4 4]) 
(f '[2 2 2 4 4 8]) 
(f '[2 2 2 2]) 
(f '[4 4 2 8 8 2])
(f '[1024 1024 512 512 256 256]) 
(f '[3 3 3 1 1 7 5 5 5 5])
(f '[3 3 3 1 1 7 5 5 5 5 5])

เอาท์พุท:

'()
'(4 8)
'(2 4 8 8)
'(4 4)
'(8 2 16 2)
'(2048 1024 512)
'(3 6 2 7 10 10)
'(3 6 2 7 5 10 10)

1

Japt , 12 ไบต์

ò¦ ®ò2n)mxÃc

ลองออนไลน์!

เอาออกแล้วมันทำงานอย่างไร

Uò!= mZ{Zò2n)mx} c

Uò!=    Partition the input array where two adjacent values are different
        i.e. Split into arrays of equal values
mZ{     Map the following function...
Zò2n)     Split into arrays of length 2, counting from the end
          e.g. [2,2,2,2,2] => [[2], [2,2], [2,2]]
mx        Map `Array.sum` over it
}
c       Flatten the result

มีความคิดจากการแก้ปัญหาวุ้นโจนาธานอัลลัน


0

Mathematica, 51 ไบต์

Abs[#//.{Longest@a___,x_/;x>0,x_,b___}:>{a,-2x,b}]&

{Longest@a___,x_/;x>0,x_,b___}-2xตรงกับรายการที่มีตัวเลขสองบวกติดต่อกันเหมือนกันและการแปลงเหล่านี้ตัวเลขสองเข้าไปLongestบังคับให้การแข่งขันเกิดขึ้นช้าที่สุดเท่าที่จะทำได้

กระบวนการนี้เป็นตัวอย่างทีละขั้นตอน:

   {3, 3, 3, 1, 1, 7, 5, 5, 5, 5}
-> {3, 3, 3, 1, 1, 7, 5, 5, -10}
-> {3, 3, 3, 1, 1, 7, -10, -10}
-> {3, 3, 3, -2, 7, -10, -10}
-> {3, -6, -2, 7, -10, -10}
-> {3, 6, 2, 7, 10, 10}

0

เป็นกลุ่ม 28 ไบต์

G@='?\v(\d+)\n\1<C-@>DJ@"<C-A>-@=<C-@>'<CR>

แมโครที่ regex ค้นหาย้อนหลังเพื่อจับคู่หมายเลขที่ต่อเนื่องกันและเพิ่มเข้าด้วยกัน

อาร์เรย์อินพุตต้องมีหนึ่งหมายเลขต่อหนึ่งบรรทัด รูปแบบนี้ช่วยให้ฉันประหยัดซึ่งเป็นสิ่งที่ดี แต่เหตุผลที่แท้จริงคือการแก้ไขการจับคู่ regex ที่ทับซ้อนกัน รับสาย222ถ้าคุณ/22จะจับคู่คู่แรกเท่านั้นไม่ใช่คู่ที่ทับซ้อนกัน กฎการทับซ้อนจะแตกต่างกันเมื่อทั้งคู่เริ่มต้นในบรรทัดที่แตกต่างกัน ในความท้าทายนี้[2, 2, 2]จะกลายเป็น[2, 4]ดังนั้นการจับคู่คู่ที่ทับซ้อนกันจึงเป็นสิ่งสำคัญ

หมายเหตุ:ความท้าทายขอผ่านเพียงครั้งเดียว :set nowrapscanสำหรับเหตุผลที่คุณจะต้องมี ด้วย:set wrapscanฉันสามารถสร้างเวอร์ชันที่เสร็จงานหลายรอบแม้ว่าวิธีแก้ปัญหานี้เป็นลายลักษณ์อักษรจะไม่ทำอย่างนั้น

  • <C-@>: โดยปกติในบรรทัดคำสั่งที่จะพิมพ์ตัวอักษรโดยไม่ต้องใช้คำสั่งที่คุณจะต้องหลบหนีด้วย<CR> <C-V>แต่คุณสามารถพิมพ์<C-@>unescaped และมันจะถือว่าเป็น<C-J>/ <NL>ซึ่งจะเป็นเหมือน<CR>เมื่อคุณเรียกใช้แมโคร แต่ไม่เมื่อคุณพิมพ์ :help NL-used-for-Nulลองอ่าน
  • @=: ฉันไม่สามารถใช้มาโครที่บันทึกไว้ได้อย่างง่ายดายในเวลานี้เนื่องจากมีความเป็นไปได้ที่อินพุตอาจไม่มีคู่ที่ตรงกัน หากสิ่งนั้นเกิดขึ้นขณะเรียกใช้แมโครการค้นหาที่ไม่สำเร็จจะทำให้แมโครนั้นล้มเหลว แต่ถ้ามันเกิดขึ้นในระหว่างการบันทึก (โดยปริยายแรก) คำสั่งส่วนที่เหลือของคำสั่งโหมดปกติจะทำงานและทำให้ไฟล์เสียหาย ข้อเสีย@=คือฉันเสียไบต์ในการโทรซ้ำ บางครั้งคุณสามารถใช้@@เป็นการเรียกซ้ำ แต่จะเรียกใช้@"จาก 4 ไบต์ก่อนหน้านี้ในกรณีนี้
  • DJ@"<C-A>-: DJลบบรรทัดและใส่หมายเลข (ไม่มีการขึ้นบรรทัดใหม่) ในการลงทะเบียนดังนั้นฉันสามารถเรียกใช้มันเป็นมาโครสำหรับอาร์กิวเมนต์ตัวเลข<C-A>ได้ ฉันต้อง-หลังจากนั้นฉันจึงไม่ได้นัดที่สองในกรณีเช่น[4, 2, 2]นี้


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.