รหัสที่ตามมาเพิ่มขึ้นยาวที่สุดที่สั้นที่สุด


11

ความท้าทายคือการเขียนที่สั้นที่สุดการดำเนินการเพื่อหาสิ่งที่เพิ่มขึ้น subsequence

ตัวอย่าง : ให้ S เป็นลำดับ 1 5 7 1 8 4 3 5 [ความยาวของ S = 8]

  • เรามีความยาวย่อย 1 ลำดับ 0 [จะพิจารณาเพิ่มขึ้น]
  • 6 ลำดับย่อยของความยาว 1 {1,5,7,8,4,3} [ทั้งหมดถือว่าเพิ่มขึ้น]
  • (7 * 8) / 2 sub-sequences ของ length 2 [แต่เราจะลบรายการที่ซ้ำกัน], sub-seq ที่เพิ่มขึ้นจะเป็นสีดำเข้ม
    { 15,17 , 11, 18,14,13,57 , 51, 58 , 54,53,55,71, 78 , 74,73,75,84,83,85,43, 45,35 }

[โปรดทราบว่าเราสนใจเฉพาะลำดับย่อยที่เพิ่มมากขึ้นเท่านั้น]

[คุณไม่สามารถเปลี่ยนลำดับขององค์ประกอบภายในลำดับได้ดังนั้นจึงไม่มีลำดับย่อย [37] ในลำดับตัวอย่าง]

  • เรามีการเพิ่มซีเควนซ์ย่อยของความยาว 4 ซึ่งคือ 1578 แต่ไม่มีซีเครตย่อยของความยาว 5 ดังนั้นเราจึงพิจารณาความยาวของลำดับย่อยที่เพิ่มขึ้นที่ยาวที่สุด = 4

อินพุต :

a 1 a 2 ... a N (ลำดับ)

ตัวเลขทั้งหมดเป็นจำนวนเต็มบวกน้อยกว่า 10 3
N <= 1,000

ผลผลิต :

เลขจำนวนเต็มหนึ่งค่าที่แสดงถึงความยาวของลำดับย่อยที่เพิ่มขึ้นที่ยาวที่สุดของลำดับอินพุต

sample input(1)
1 2 4 2 5
sample output(1)
4

sample input(2)
1 5 7 1 8 4 3 5
sample output(2)
4

รหัสของคุณควรจะทำงานในเวลาที่เหมาะสมโปรดทดสอบรหัสของคุณในกรณีนี้ก่อนที่จะส่งที่นี่

คุณสามารถรับอินพุตจากไฟล์ / stdin หรือเป็นพารามิเตอร์ฟังก์ชั่นและคุณสามารถพิมพ์เอาต์พุตไปยังไฟล์ / stdout หรือเพียงแค่คืนค่าถ้าคุณเขียนฟังก์ชั่น

คณะกรรมการให้คะแนน

  1. เดนนิส CJam - 22
  2. isaacg Pyth - 26
  3. Howard GolfScript - 35
  4. haskeller ภูมิใจ Haskell - 56
  5. Ray Python 3 - 66
  6. ฮิสโทแกตทับทิม - 67
  7. DLeh C # - 92
  8. YosemiteMark Clojure - 94
  9. faubiguy Python 3 - 113

1
"เรามีลำดับย่อยความยาว 1 0 [จะพิจารณาเพิ่มขึ้น]" ในทางเทคนิคคุณมีจำนวนย่อยลำดับ 0 ความยาวไม่สิ้นสุด :)
Cruncher

ที่จริงฉันต้องเปลี่ยนคำสั่งเพื่อให้ "ชุด" ทั้งหมดต้องลบรายการที่ซ้ำกันเช่น {1,5,7,1,8,4,3,5}} ควรเป็น {1,5,7,8,4 , 3} และจากนั้นเราสามารถพูดได้ว่ามีการเรียงลำดับความยาว 1 0 ใน "ชุด" ขอบคุณ
Mostafa 36a2

1
สำหรับฟังก์ชั่นเราควรนับจำนวนไบต์ของฟังก์ชั่นด้านนอก ( function f(){...}) หรือฟังก์ชั่นด้านใน (แค่...)? หากเรานับฟังก์ชั่นด้านนอกฟังก์ชั่นที่ไม่ระบุชื่อจะได้รับอนุญาตหรือไม่
เดนนิส

เรานับฟังก์ชั่นด้านนอกและอนุญาตให้ใช้ฟังก์ชั่นนิรนามได้ แต่อย่าพลาดในการทดสอบเวอร์ชั่น (เวอร์ชั่นสมบูรณ์พร้อมการจัดการอินพุต / เอาท์พุต)
Mostafa 36a2

คำตอบ:


2

CJam, 22 ไบต์

1e3,q~{_2$<$0=(t}/$0=z

ลองออนไลน์

ตัวอย่าง

$ cjam subsequence.cjam <<< '[2 1]'; echo
1
$ cjam subsequence.cjam <<< '[1 9 2 4 3 5]'; echo
4

โปรแกรมจะพิมพ์57สำหรับกรณีทดสอบนี้หลังจาก 0.25 วินาที

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

ผมเอาความคิดทั่วไปจาก@ คำตอบของเรย์

1e3,    " Push the array [ 0 ... 999 ] (J).        ";
q~      " Read from STDIN and evaluate.            ";
{       " For each integer (I) of the input array: ";
  _2$<  " Push [ J[0] ... J[I - 1] ] (A).          ";
  $0=(  " Compute min(A) - 1.                      ";
  t     " Update J[I] with the value on the stack. ";
}/      "                                          ";
$0=     " Compute abs(min(J)).                     ";

5

Python 3, 66

โปรดทราบว่าตัวเลขทั้งหมดอยู่ในช่วง [1, 999] เราสามารถใช้อาร์เรย์bเพื่อรักษาความยาวของลำดับที่ยาวที่สุดที่ลงท้ายด้วยแต่ละหมายเลข b[x] = dหมายถึงว่า subsequence ที่ยาวที่สุดที่ลงท้ายด้วยมีความยาวx dสำหรับแต่ละหมายเลขจากอินพุตเราจะอัปเดตอาร์เรย์โดยใช้b[x] = max(b[:x]) + 1และจากนั้นเราก็สามารถทำงานให้เสร็จได้โดยmax(b)สุดท้าย

ความซับซ้อนของเวลาคือ บน) O (mn)โดยที่m1,000 เสมอและnคือจำนวนองค์ประกอบอินพุต

def f(a):
 b=[0]*1000
 for x in a:b[x]=max(b[:x])+1
 return max(b)

ว้าวดูเหมือนว่าไม่เรียบร้อยแล้ว :) คุณสามารถทดสอบโดยใช้ stdin / stdout โดยเพิ่มบรรทัด:

print(f(map(int,input().split())))

for x in a: max(b)ดูสวยมาก O (n ^ 2)
โฮเวิร์ด

@ วิธีมันO(1000 n)และ 1,000 เป็นค่าคงที่ O(m n)นอกจากนี้คุณยังสามารถคิดว่ามันเป็น
เรย์

3
ด้วยการโต้แย้งเช่นการสนทนาทั้งหมดจะไม่ได้ผลเพราะการป้อนข้อมูลที่ จำกัด ซับซ้อนอยู่เสมอO(1);-)
ฮาวเวิร์ด

@Howard ฉันมาจากโลกของ ACM-ICPC และนี่ค่อนข้างจะเป็นการประชุมที่นั่น คุณสามารถคิดว่ามันเป็น O (mn) มันยังคงแตกต่างจาก O (n ^ 2) อย่างไรก็ตามเวลาที่เสียค่าใช้จ่ายจะน้อยกว่าเวลาเริ่มต้นใช้งานล่ามดังนั้นฉันคิดว่ามันเร็วพอ
เรย์

อัลกอริทึมสั้น ๆ ที่น่าประทับใจ! ฉันเห็นได้เพียงตัวเดียว (อย่างน้อยเมื่อเปลี่ยนไปใช้ Python 2): คุณสามารถพิมพ์ผลลัพธ์ จะสั้นกว่าprint return
Falko

3

Python - 113

a=[]
for i in map(int,input().split()):
 if not a or i>a[-1]:a+=[i]
 z=0
 while a[z]<i:z+=1
 a[z]=i
print(len(a))

ทางออกที่ยอมรับ รหัสของคุณได้รับการทดสอบที่นี่และที่นี่
Mostafa 36a2

@ Mostafa36a2 คำว่า "ยอมรับ" มีความหมายอื่นในเว็บไซต์นี้ ฉันคิดว่าสิ่งที่คุณหมายถึงคือ "ยอมรับได้"
เรย์

ขออภัยใช่ฉันหมายถึงยอมรับเร็วเกินไปที่จะเลือกที่ยอมรับ
Mostafa 36a2

ด้วยเส้นa+=[i]*(a==[]or i>a[-1]);z=0และการพิมพ์len(a)(โดยไม่ต้องวงเล็บ) คุณสามารถบันทึก 4 ตัวอักษร
Falko

3

Pyth , 26 29 33 39

J*]0^T3Fkyw=@JkheS:J0k)eSJ

วิธีแก้ปัญหาพอร์ตของ @ ray ผ่านการทดสอบอย่างเป็นทางการ ตอนนี้ใช้อินพุต STDIN ที่คั่นด้วยช่องว่างไม่ใช่การเรียกใช้ฟังก์ชัน

เรียกใช้ดังนี้:

./pyth.py -c "J*]0^T3Fkyw=@JkheS:J0k)eSJ" <<< "1 5 7 2 8 4 3 5"
4

คำอธิบาย:

J*]0^T3                 J = [0]*10^3
Fkyw                    For k in space_sep(input()):
=@Jk                    J[k]=
heS:J0k                 max(J[0:k])+1
)                       end for
eSJ                     max(J)

เวลาไม่ จำกัด :

Pyth , 18

L?eS,ytbhyf>Thbbb0

หมายเหตุด้านเทคนิค: ฉันสังเกตเห็นข้อผิดพลาดในการรวบรวม Pyth ของฉันขณะเขียนกอล์ฟ Lไม่ทำงาน นั่นเป็นเหตุผลที่มีความมุ่งมั่นล่าสุดไปยังที่เก็บคอมไพล์ข้างต้น


รหัสของคุณไม่ทำงานในเวลาที่เหมาะสมสำหรับกรณีที่มีรายการขนาดใหญ่ (พูด 100 องค์ประกอบ)
Mostafa 36a2

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

ขออภัยที่ฉันพูดถึงว่าไม่ใช่ runtime แต่อย่างน้อย [เวลาที่เหมาะสม] ไม่มีปัญหาหากรหัสใช้เวลา 10-20 นาทีหรือแม้กระทั่งชั่วโมง แต่โซลูชัน O (2 ^ n) จะไม่ให้ผลลัพธ์ในระหว่าง ชีวิตอันยาวนานของเรา
Mostafa 36a2

@ Mostafa36a2 เข้าใจแล้วฉันเพิ่งสังเกตเห็นบรรทัดนั้น ฉันจะทำการปรับปรุง
isaacg

1
ขออภัยฉันเห็นการปรับปรุงในขณะนี้โปรดลองกรณีนี้และบอกฉันว่ามันใช้งานได้
Mostafa 36a2

3

Clojure, 94 ตัวอักษร

การใช้วิธีการของ @ Ray ในการอัปเดตผลลัพธ์ในเวกเตอร์ 1,000 รายการ:

(defn g[s](apply max(reduce #(assoc % %2(inc(apply max(take %2 %))))(into[](repeat 1e3 0))s)))

ตามคำขอพร้อมด้วยคำสั่งพิมพ์ (จะพิมพ์คำตอบและกลับศูนย์) ข้อมูลที่ป้อนควรเป็นเวกเตอร์ (g [1 2 3]) หรือรายการ (g '(1 2 3)):

(defn g[s](prn(apply max(reduce #(assoc % %2(inc(apply max(take %2 %))))(into[](repeat 1e3 0))s))))

คุณสามารถเพิ่มคำสั่งการพิมพ์เพื่อให้สามารถทดสอบได้หรือไม่ มันจะไม่ถูกนับในคะแนน
Mostafa 36a2

1
Updated ฉันใช้ทั้งตัวอย่างขนาดใหญ่ของคุณและได้ 58 และ 57 ตามที่คาดไว้
YosemiteMark

ฉันคิดว่าคุณยังคงต้องเรียกใช้ฟังก์ชัน: p แต่ถ้าคุณทดสอบแล้วนั่นก็เพียงพอแล้ว
Mostafa 36a2

3

Haskell, 58 57 56 ตัวอักษร

(x:s)%v|v>x=x:s%v|0<1=v:s
_%v=[v]
l s=length$foldl(%)[]s

นี่ใช้อัลกอริทึมที่ฉันเห็นครั้งเดียวบนอินเทอร์เน็ต แต่ฉันหามันไม่เจอ ใช้เวลาในการทดสอบ GHCi กับคอมพิวเตอร์ของฉัน (อาจจะเร็วกว่านี้หากคอมไพล์แล้ว)


อัลกอริทึมที่คุณกล่าวถึงเป็นเช่นเดียวกับที่ใช้โดย @faubiguy
เรย์

@Ray คุณพูดถูก
ภูมิใจ Haskeller

2

GolfScript, 35 ตัวอักษร

~]]){1${~2$<*)}%1+$-1>[\+]+}/$-1=0=

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

ตัวอย่าง:

> 1 5 7 1 8 4 3 5
4

> 5 1 9 9 1 5
2

1
@ MartinBüttnerใช้เวลาประมาณ 5 วินาทีในการรับ 1,000 หมายเลขในคอมพิวเตอร์ของฉัน สมมติว่า$เป็น O (n log n) อัลกอริทึมคือ O (n ^ 2 log n)
Howard

โปรดลองใส่ในลิงค์นี้
Mostafa 36a2

@ Mostafa36a2 ฉันทำไปแล้ว (ดูความคิดเห็นก่อนหน้า) หลังจาก 5 วินาทีมันจะคืน 58.
Howard

นี่คืออีกอันมันควรจะคืน 57 ดังนั้นถ้ารหัสของคุณกลับ 57 แล้วก็ยอมรับ :) ขอแสดงความยินดี
Mostafa 36a2

@ Mostafa36a2 Ah, ตอนนี้ฉันเห็นว่าเป็นสองกรณีทดสอบที่แตกต่างกัน ใช่ลิงค์ที่สองของคุณคืน 57 เช่นเดียวกับวิธีการแก้ปัญหาของฉันในการป้อนข้อมูลนี้
โฮเวิร์ด

2

ทับทิม, 67

s=Hash.new{|s,a|f,*r=a
s[a]=f ?[1+s[r.select{|x|x>f}],s[r]].max: 0}

สิ่งนี้จะทำงานใน 30 วินาทีสำหรับอินพุตขนาดใหญ่นับเป็นเวลาที่เหมาะสมหรือไม่? : p

มันเป็นการเรียกซ้ำแบบสัตว์เดรัจฉาน แต่มีบันทึกช่วยจำบางอย่าง


1
ใช่นี่เป็นเวลาที่เหมาะสม :)
Mostafa 36a2

2

C #, 172 92 ตัวอักษร

ไม่มีอะไรพิเศษ แต่ฉันทำมันดังนั้นฉันจึงคิดว่าฉันก็สามารถส่งมันได้เช่นกัน

int a(int[] j){int c=2,m=2,i=1;for(;++i<j.Length;){c=j[i]>j[i-1]?c+1:2;m=c>m?c:m;}return m;}

ขอบคุณ Armin และ Bob สำหรับการปรับปรุงของพวกเขา!


1
คุณสามารถเปลี่ยนพารามิเตอร์ของคุณเป็น int [] จากนั้นคุณจะมีตัวอักษรน้อยลงเพราะคุณไม่จำเป็นต้องแปลงสตริงเป็น int
Armin

2
ช่องว่างโดยรอบ=>ไม่จำเป็น นอกจากนี้คุณยังสามารถย้ายi=0ประกาศนอกวงไปfor int c=2,m=2,i=0;for(;นอกจากนี้คุณยังสามารถวางวงเล็บปีกกาไว้รอบ ๆforร่างกายได้เนื่องจากคุณมีเพียงข้อความเดียวในนั้น
Bob

และc++;if(c>m)m=c;สามารถเป็นได้m=c++>m?m:c;และคุณสามารถวางวงเล็บปีกกาอีกรอบ
บ๊อบ

1
ในความเป็นจริงคุณยังสามารถยกเลิกif(i>0)การตรวจสอบโดยการforเริ่มต้นวงที่ 1 คุณยังสามารถลดปัญหาก่อนหน้านี้ลงในint c=2,m=2,i=0;for(;i<j.Length;i++)if(i>0) int c=2,m=2,i=0;for(;i++<j.Length;)ส่วนทั้งหมดนั้นสามารถเปลี่ยนเป็นint c=2,m=2,i=0;for(;i++<j.Length;){c=j[i]>j[i-1]?c+1:2;m=c>m?m:c;}(ใช้ ternary อื่นเพื่อแทนที่ส่วนที่เหลือล่าสุดif- กฎง่ายๆคือ ternaries สั้นหากifร่างกายของคุณเป็นเพียงการมอบหมาย
Bob

2
ขออภัย - พิมพ์ผิดในความคิดเห็นก่อนหน้านี้ฉันควรจะเป็นm=c>m?m:c m=c>m?c:mและถ้าคุณเพิ่มคำแนะนำของ @ Armin คุณจะได้รับ 92 ไบต์เกือบจะลดลงครึ่งหนึ่ง! int a(int[] j){int c=2,m=2,i=0;for(;i++<j.Length;){c=j[i]>j[i-1]?c+1:2;m=c>m?c:m;}return m;}
บ๊อบ

2

J , 19 ไบต์

[:#]`I.`[} ::,~/@|.

ลองออนไลน์!

รันในO (n log n)โดยใช้การเรียงลำดับความอดทนที่แก้ไขเนื่องจากมีความยาวไม่จำเป็นต้องเป็นลำดับจริง

คำอธิบาย

[:#]`I.`[} ::,~/@|.  Input: array
                 |.  Reverse
               /     Reduce right-to-left
     I.                Find the index to insert while keeping it sorted
                       (uses binary search)
         }             Amend the current search array at that index with the next value
           ::          If error (when the index is not found)
             ,           Append the value at the end
 #                   Length of that array

1

Bash + coreutils, 131 ไบต์

วิธีการแก้ปัญหานี้ล้มเหลวอย่างมากตามความต้องการในเวลาที่กำหนดและไม่สั้นโดยเฉพาะ แต่ฉันชอบว่าสิ่งนี้เป็นไปได้ในทางทฤษฎีอย่างน้อยที่สุดในเชลล์สคริปต์ดังนั้นฉันจึงโพสต์ต่อไป สิ่งนี้จะทำงานโดยมีความซับซ้อนของเวลาชั่วนิรันดร์ของ O (2 ^ n)

s=${1//,/,:\},\{}
a=`eval echo "{$s,:}"`
for s in $a;{
b="$(tr , \\n<<<$s|grep -v :)"
sort -nC<<<"$b"&&wc -w<<<$b
}|sort -nr|sed 1q

อินพุตเป็นรายการที่คั่นด้วยเครื่องหมายจุลภาคที่ส่งผ่านเป็นอาร์กิวเมนต์บรรทัดคำสั่งเดียว:

$ time ./slisc.sh 1,5,7,1,8,4,3,5
4

real    0m1.240s
user    0m0.518s
sys 0m0.689s
$ 

การขยายรั้งจะใช้ในการสร้างรายการขององค์ประกอบที่เป็นไปได้ทั้งหมด

  • บรรทัดแรกแทนที่คอมมาด้วย,:},{ซึ่งสร้างสตริงเหมือน1,:},{5,:},{7,:},{1,:},{8,:},{4,:},{3,:},{5
  • {1,:},{5,:},{7,:},{1,:},{8,:},{4,:},{3,:},{5,:}บรรทัดที่สองเสร็จสมบูรณ์สายนี้ด้วยเครื่องหมายวงเล็บจุลภาคและอัฒภาคที่จะให้นี้ นี่เป็นส่วนขยาย bash brace ที่ถูกต้องซึ่งเมื่อevaled พร้อมกับechoสร้างรายการที่คั่นด้วยช่องว่างนี้1,5,7,1,8,4,3,5 1,5,7,1,8,4,3,: 1,5,7,1,8,4,:,5 1,5,7,1,8,4,:,: ...
  • โดยค่าเริ่มต้นทุบตีสตริงด้วยช่องว่างดังนั้นเราวนรอบองค์ประกอบของรายการนี้:
    • เครื่องหมายจุลภาคจะถูกแทนที่ด้วยการขึ้นบรรทัดใหม่จากนั้นบรรทัดที่มีเครื่องหมายโคลอนจะถูกลบออกให้รายการที่คั่นด้วยบรรทัดใหม่สำหรับแต่ละลำดับที่เป็นไปได้
    • จากนั้นเราsort -Cจะทดสอบเพื่อเพิ่มลำดับและถ้าเป็นเช่นนั้นใช้wc -wในการพิมพ์ความยาวของรายการ
  • รายการผลลัพธ์ของความยาวรายการจะถูกเรียงกลับกันและค่าแรกที่พิมพ์เพื่อให้ความยาวการเรียงลำดับที่เพิ่มขึ้นยาวที่สุด

1

Stax , 21 ไบต์

ë/NS7Γ╥╚┌{1╤╒¬è¶²╢╦┌☼

เรียกใช้และแก้ไขข้อบกพร่อง

กรณีนี้มีสองกรณีทดสอบหนึ่งในนั้นคือกรณี 1,000 องค์ประกอบ มันรันหนึ่งใน 24 วินาทีบนเครื่องของฉัน มันใช้วิธีการเขียนโปรแกรมแบบไดนามิกคลาสสิกสำหรับปัญหาประเภทนี้


0

J 34

โปรดทราบว่าฉันอ่านอินพุตมาตรฐานเช่นกัน

>./;+/@:*&.>(<*>.)/\&.><\.".1!:1]3

หากไม่ได้อ่านอินพุตมาตรฐานเนื้อสัตว์จะมีอักขระ 26 ตัว

>./;+/@:*&.>(<*>.)/\&.><\.

เพิ่งสังเกตเห็นฉันทำงานช้าสำหรับการป้อนข้อมูลขนาดใหญ่โอ้ดี



0

C # (. NET Core) 155 ไบต์

ใช้อาร์เรย์เพื่อคำนวณการสิ้นสุดการเรียงลำดับที่เพิ่มขึ้นที่ยาวที่สุดที่แต่ละตำแหน่งในอาร์เรย์อินพุต (การเขียนโปรแกรมแบบไดนามิก) จากนั้นส่งคืนค่าที่ใหญ่ที่สุด ตัวอย่างเช่นอาร์เรย์ที่คำนวณสำหรับอินพุต[1,5,7,1,8,4,3,5]จะเป็น[1,2,3,1,4,2,2,3]และ4จะส่งคืนค่าที่ใหญ่ที่สุด

int b(int[]x){int l=x.Length,r=1,i=0,j,c;var a=new int[l];a[0]=1;while(++i<l)for(j=0;j<i;j++){c=x[j]<x[i]?a[j]+1:1;a[i]=a[i]<c?c:a[i];r=r<c?c:r;}return r;}

ลองออนไลน์!


0

ภาษา Wolfram (Mathematica) , 38 ไบต์

Length@LongestOrderedSequence[#,Less]&

ลองออนไลน์!

แน่นอนว่ามีMathematicaในตัวสำหรับค้นหาลำดับที่ยาวที่สุด ชื่อของมันยาวมาก: มันเป็นทางออกมากกว่าครึ่งและฉันจะไม่แปลกใจถ้ามีคนออกไปเล่นกอล์ฟทางออกนี้

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