เลือกไม้ที่ยาวที่สุด


13

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

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

นี่คือกฎของปริศนา

  1. คุณจะได้รับเมทริกซ์ 2D โดยที่แต่ละคอลัมน์แสดงถึงแท่ง
  2. ในแต่ละคอลัมน์ 1 หมายถึงส่วนหนึ่งของไม้และ 0 เป็นพื้นที่ว่าง
  3. เมื่อไปจากบนลงล่างในแต่ละคอลัมน์เริ่มแรกคุณมี0และทันทีที่คุณกดปุ่ม1เริ่มและส่วนที่เหลือของคอลัมน์จะเต็มไปด้วย1เพียง
  4. คุณสามารถเขียนโปรแกรมของคุณเพื่อเลือกหนึ่งคอลัมน์ ขนาดของไม้เท้าในคอลัมน์นั้นจะเป็นตัวกำหนดผู้ชนะ / ผู้แพ้ ขนาดของแท่ง == จำนวน 1s ในคอลัมน์นั้น
  5. อย่างไรก็ตามโปรแกรมนั้นสามารถมีความซับซ้อนของเวลาเชิงเส้นตรงที่เลวร้ายที่สุดเท่านั้น

ในฐานะที่คุณทุกคนเป็นโปรแกรมเมอร์คุณจะรู้ว่าโปรแกรมของคนอื่นกำลังถ่ายภาพเวลาที่จำกัดความซับซ้อน

งานของคุณคือ:

  • เขียนโปรแกรมหรือฟังก์ชั่นที่รับอินพุตในรูปแบบ 2D หรืออาร์เรย์ของสตริง
  • อินพุตสามารถนำมาจาก STDIN / prompt / console หรืออาร์กิวเมนต์ของฟังก์ชัน
  • หากคุณกำลังอ่านอินพุตจาก STDIN / พรอมต์คุณสามารถสันนิษฐานได้ว่าการอ่านอินพุตและการแปลงเป็นอาเรย์นั้นใช้เวลา 0 (แม้ว่ารหัสจะต้องมีในคำตอบของคุณ)
  • กำหนดคอลัมน์ด้วยแท่งที่ยาวที่สุดในนั้น
  • เอาต์พุตสามารถเป็นค่าส่งคืนของฟังก์ชันหรือไปยัง STDOUT / console / alert
  • โปรแกรม / ฟังก์ชั่นจะต้องมีความซับซ้อนของเวลาที่เลวร้ายที่สุดเชิงเส้นตรงO(m+n)ซึ่งmเป็นจำนวนแถวและnจำนวนคอลัมน์

อินพุตอาจเป็นหนึ่งในรูปแบบต่อไปนี้:

อาร์เรย์ 2 มิติ:

[ [0, 0, 0, 0],
  [1, 0, 0, 0],
  [1, 1, 0, 1],
  [1, 1, 1, 1] ]

Array of Strings:

[ "0000", "1000", "1101", "1111" ]

อินพุตจะมีคุณสมบัติดังต่อไปนี้:

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

นี่คือรหัสของกอล์ฟที่สั้นที่สุดที่จะชนะ ! *

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

อัพเดท ความซับซ้อนของเวลาเชิงเส้นตรงนี้หมายถึง O (n + m) โดยที่ n คือขนาดคอลัมน์และ m คือขนาดแถว (สำหรับผู้ที่ไม่ชัดเจน)

อัพเดท 2 สิ่งนี้สามารถทำได้ในเวลาเชิงเส้น และถ้าคุณโพสต์คำตอบอย่าลังเลที่จะโพสต์ตรรกะ / อัลกอริทึมภายในสองสามวันเพื่อต่อสู้อย่างยุติธรรม :)

UPDATE 3ฉันจะตอบคำถามทั้งหมดภายในสองสามชั่วโมงเพื่อตรวจสอบความซับซ้อนของเวลาและโปรแกรม :)


2
ฉันยืนยันว่าสิ่งนี้ไม่สามารถทำได้ใน O (n + m) เนื่องจากแต่ละเซลล์สามารถมีค่าที่สำคัญ (เช่น "1" แรกของแท่ง / คอลัมน์ที่ยาวที่สุด) ดังนั้นคุณต้องดูแต่ละเซลล์ซึ่งใช้ O (n * m)
Falko

อาจมีคอลัมน์ว่างเปล่าได้ไหม
Martin Ender

@Optimizer: โอ้ฉันเข้าใจแล้ว คุณถูก. :)
Falko

11
มันไม่สามารถทำได้ใน O (n + m) เมื่ออินพุตถูกแปลงเป็นรูปแบบที่อนุญาตให้เข้าถึงแบบสุ่มแล้วการประมวลผลที่เหลือสามารถเป็น O (n + m) แต่คุณต้องเขียนโปรแกรมและในกรณีที่แย่ที่สุดที่เฉพาะ1ในอินพุตนั้นเป็นเซลล์สุดท้าย จำเป็นต้องอ่านอินพุตทั้งหมด แม้ว่าไลบรารี่มาตรฐานของภาษาจะสุ่มเข้าถึง stdin ภายใต้ฉากมันจะบัฟเฟอร์และดังนั้นเวลาที่ใช้คือโอเมก้า (n * m)
Peter Taylor

2
หากคุณต้องการอนุญาตให้ผู้ใช้ " เพียงแค่สร้างฟังก์ชั่นที่ยอมรับอาเรย์ " คำถามก็ไม่ควรระบุว่าพวกเขาจะต้องเขียนโปรแกรม และถ้าคุณต้องการโซลูชันที่อยู่ใน O (N ^ 0.5) โดยที่ N คือขนาดของอินพุตคุณไม่ควรถามถึงการแก้ปัญหาเชิงเส้นเวลา การแก้ปัญหาเวลาเชิงเส้นสามารถอ่านอินพุตทั้งหมด
Peter Taylor

คำตอบ:


4

GolfScript, 45 ตัวอักษร

:^,:y;0:x{^y(=x=2%y*{y(:y;x\}{x):x}if^0=,<}do

รับอินพุตเป็นอาร์เรย์ของสตริงส่งคืนดัชนี (อิง 0) ของคอลัมน์ที่สูงที่สุด มันทำงานในการทำซ้ำO ( แถว + คอลัมน์ ) และการทำซ้ำแต่ละครั้งควรใช้เวลาคงที่เป็นหลัก (อย่างน้อยสมมติว่าเลขคณิตเวลาคงที่) การดำเนินการของอาเรย์ / สตริงเพียงอย่างเดียวที่กระทำภายในลูปคือการค้นหาองค์ประกอบ ( =) และการรับความยาวของสตริง ( ,) ซึ่งทั้งสองอย่างใช้เวลาคงที่ใน GolfScript

ลองออนไลน์

คำอธิบาย:

เช่นเดียวกับวิธีแก้ปัญหาส่วนใหญ่ที่นี่รหัสนี้ทำงานโดยเริ่มต้นที่มุมล่างซ้ายของเมทริกซ์การเดินขึ้นหรือขวาขึ้นอยู่กับว่าองค์ประกอบปัจจุบันของเมทริกซ์คือ 1 หรือ 0 และติดตามคอลัมน์ที่มันเลื่อนขึ้นล่าสุด .

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

ภายในวงหลัก, ^y(=x=สารสกัดจากxตัวละคร -th ของy-1แถว -th ^ใน สิ่งนี้จะส่งคืนรหัส ASCII ของตัวละครดังนั้นจึง2%จำเป็นต้องวางทั้งหมดยกเว้นบิตสุดท้าย ในกรณีพิเศษถ้าyเท่ากับ 0 (ซึ่งสามารถเกิดขึ้นได้หากคอลัมน์ที่สูงที่สุดที่พบจนถึงจนถึงแถวบนสุด) บิตที่ค้นหาจะมาจากแถวสุดท้ายในเมทริกซ์ (ดัชนี -1) แต่ การy*บังคับต่อไปนี้เป็นศูนย์จึงสร้างแถวศูนย์ทั้งหมดเสมือนที่ด้านบนของเมทริกซ์ได้อย่างมีประสิทธิภาพ

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

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

ps จากการทดสอบของฉันมันเป็นไปได้ที่จะทำให้โปรแกรมนี้สั้นลงด้วยอักขระหนึ่งตัวโดยแทนที่การทดสอบความยาวสายอักขระ,<ที่ส่วนท้ายของลูปด้วย>ซึ่งจะตัดสตริงที่ดัชนีที่กำหนดและส่งคืนส่วนท้าย (ซึ่งจะว่างเปล่าและ ดังนั้นจึงเป็นเท็จในตอนท้ายของลูป) อย่างไรก็ตามในขณะที่การตัดสตริงแบบที่ดูเหมือนว่าจะถูกนำมาใช้เป็นการดำเนินการเวลาคงที่ใน GolfScript (หรือใน Ruby ซึ่ง GolfScript ทำงานอยู่ด้านบน) ฉันไม่พบเอกสารที่เป็นทางการใด ๆ ที่พูดเช่นนั้น เพื่อความปลอดภัยฉันเลือกที่จะใช้คุณสมบัติที่ยาวกว่าเล็กน้อย แต่แน่นอนว่า O (1) เวอร์ชันด้านบน


6

Ruby, 83 75 68 66 63 ไบต์

f=->m{m[b=c=i=0].map{(c=i;b-=1)while(r=m[b-2])&&r[i]>0;i+=1};c}

กำหนดฟังก์ชันfซึ่งใช้รูปแบบอาร์เรย์ 2D เป็นอินพุต

ฉันเริ่มที่ด้านล่างซ้ายติดตามความยาวแท่งสูงสุด (อันที่จริงลบด้วย) และคอลัมน์ที่เกี่ยวข้อง ในแต่ละคอลัมน์หากยังคง1มีความยาวสูงสุดของแท่งสูงสุดก่อนหน้านี้ฉันเดินขึ้นแท่งไปจนสุดและจดจำความยาวสูงสุดและคอลัมน์ใหม่ นั่นหมายความว่าฉัน iterating ครั้งเดียวพร้อมคอลัมน์และที่มากที่สุดครั้งหนึ่งพร้อมแถว (เฉพาะฉัน iterating เท่าที่ระยะเวลาในการติดสูงสุด) O(m+n)ซึ่งเป็นได้อย่างแม่นยำ


@Optimizer ฉันไม่เห็นการแก้ไขครั้งที่สองของคุณจนกว่าฉันจะโพสต์ดังนั้นจึงอยู่ในประวัติการแก้ไข นั่นเป็นเหตุผลที่ฉันใส่มันในสปอยเลอร์สำหรับคนที่ต้องการคิดออกเอง
Martin Ender

4

Python 2 - 71, 69, 73, 75 81

j=i=-1
M=input()
for m in M[0]:
 j+=1
 while-i<len(M)and M[i][j]:i-=1;J=j
print J

นี่มีจุดประสงค์เพื่อให้ทำงานใน Python 2 หรือ 3 หรือไม่ อินพุตควรเป็นอย่างไร
feersum

1
@feersum Python 2 อาร์เรย์ของอาร์เรย์
Justin

@feersum: Quincunx ถูกต้อง อินพุตเป็นอาร์เรย์ 2 มิติของ ints ตามที่คุณแนะนำ
Falko

จะไม่iออกนอกขอบเขตหากไม้ที่ใช้เต็มทั้งคอลัมน์?
xnor

1
ขออภัย แต่ดูเหมือนว่าการเปลี่ยนแปลงjที่จะนับจากการแบ่งสภาพห่วง0 i*j
xnor

2

C, 64 ไบต์

แก้ไข: ฉันเรียนรู้ว่าคำถามถามที่ตั้งของคอลัมน์ที่ยาวที่สุดไม่ใช่ความยาว

บรรทัดแรกคือรหัส golfed และส่วนที่เหลือเป็นตัวอย่างการเรียกใช้

g(int m,int n,int**a,int*r){for(*r=n;n*m;a[m][n]?m--,*r=n:--n);}

/* usage:
    m = number of rows
    n = number of columns
    a = 1-based 2D array such that a[i][j] gives the value at the ith row and jth column
    r = address of return value 
    Returns (to r) the 1-indexed location of a column with the longest length, or 0 if n=0
    */

int main()
{
    int flat[4*4] = {1, 0, 0, 0,
                     1, 0, 0, 1,
                     1, 1, 0, 1,
                     1, 1, 1, 1};
    int*twoD[4] = {flat-1,flat+3,flat+7,flat+11};
    int ret;
    g(4,4,twoD-1,&ret);
    printf("%d", ret);
    return 0;
}

// old function which determines longest length (65 bytes)
f(int m,int n,int**a,int*r){for(*r=m;n*m;a[m][n]?m--:--n);*r-=m;}

ที่น่าประทับใจ! คุณสามารถทิ้งเครื่องหมายintในฟังก์ชั่นลายมือชื่อโดยบังเอิญหรือไม่ได้เนื่องจากตัวชี้ในนั้น?
Martin Ender

1
อินพุตควรมีเฉพาะอาร์เรย์ คุณไม่สามารถบอกโปรแกรมเกี่ยวกับขนาดของอาเรย์
เครื่องมือเพิ่มประสิทธิภาพ

เดี๋ยวก่อนมันใช้งานได้จริงเหรอ? นี่ดูเหมือนจะกลับมาตามความยาวของแท่งที่ยาวที่สุดและไม่ใช่ตำแหน่ง: ideone.com/YEzqzl
Martin Ender

2
@Optimizer ที่เป็นไปไม่ได้โดยทั่วไปใน C.
Martin Ender

อาจเป็น แต่นั่นคือคำถาม :)
เครื่องมือเพิ่มประสิทธิภาพ

2

C #: 236 Chars

int p(int[,] a){int y=0,s=0,i=0,x;for(;++y<=a.GetUpperBound(0);)for(x=i;x<=a.GetUpperBound(1);){if(a[y,x++]==0)break;s=y;i++;}return s;}

ungolfed:

int p(int[,] a)
{
    int selectedRow=0;
    int maxLength=0;
    for(var y = 0; y<=a.GetUpperBound(0); y++)
        for(var x=maxLength; x<=a.GetUpperBound(1); x++)
        {
            if(a[y,x++]==0)
                break;
            selectedRow=y;
            maxLength++;
        }
    return selectedRow;
}

2

PHP 5.4 - 108 ไบต์

(113 ถ้าคุณรวมถึง<?php)

รูปแบบอินพุต: Array จะถูกอ่านเป็นสตริง JSON

php longest_stick.php "[[0, 0, 0, 0],[1, 0, 0, 0],[1, 1, 0, 1],[1, 1, 1, 1]]"

เพิ่มช่องว่างเพื่อให้สามารถอ่านได้ - บรรทัดใหม่และช่องว่างนำหน้าสามารถลบออกได้

<?php
$t=count($s=json_decode($argv[1]))-1;
foreach($s[0] as $k=>$_)
    while($s[$t][$k]) {
        $t--;
        $l = $k;
    }
echo $l?:0;

เวอร์ชันย่อ:

<?php $t=count($s=json_decode($argv[1]))-1;foreach($s[0] as $k=>$_)while($s[$t][$k]){$t--;$l=$k;}echo $l?:0;

ชนิดของการขโมยอัลกอริธึมจาก Martin ที่นี่ แต่มันดีที่ได้เล่นกับภาษาที่ไม่ค่อยเห็นบ่อยนักที่นี่ XD


@ MartinBüttnerฉันได้ "ขโมย" อัลกอริทึมของคุณดังนั้นมันควรจะ O (n + m) ตอนนี้ ฉันคิดว่ามันถูกต้อง XD
Niet the Dark Absolute

คุณสามารถแทนที่$s=json_decode($argv[1]);$t=count($s)-1;ด้วย$t=count($s=json_decode($argv[1]))-1;(-3 ไบต์)
Blackhole

@ Blackhole แน่นอนคุณสามารถ ขอขอบคุณ!
Niet the Dark Absolut

@ Blackhack ฉันคิดว่ามันจะทำลายการทำงาน มันจะทำงานที่ได้รับมอบหมายแม้ว่าจะไม่ตรงตามเงื่อนไข
Niet the Dark Absolut

@Blackhole ยังคงหยุดพักฉันเกรงว่า XD $t--จะต้องเกิดขึ้นหากพบเงื่อนไข
Niet the Dark Absolute


2

C ++ :: 78

ไม่เหมือนโซลูชัน C อื่น ๆ นี่คือโปรแกรมทั้งหมด (ไม่จำเป็นต้องเรียกใช้ไม่จำเป็นต้องบอกขนาดของอาร์เรย์) น่าเสียดายที่นี่หมายความว่าจะใช้งานได้นานกว่าmainแทนที่จะใช้ชื่อฟังก์ชั่นอักขระเดียวฉันต้องแปลอินพุตและเอาต์พุตคำตอบซึ่งโซลูชันอื่นจัดการกับ "ที่อื่น" ยังรหัสกอล์ฟครั้งแรกของฉัน
คอมไพล์ด้วยg++ file.cpp -include iostream, รันด้วย./a 000 010 110 111(ตัวอย่าง) == อาร์เรย์ของสตริง (ฉันเชื่อว่าสิ่งนี้ได้รับอนุญาตในสเป็คคำถาม)

int c;main(int r,char**v){for(r--;r*v[r][c];v[r][c]-48?std::cout<<c,r--:++c);}

เวอร์ชั่นด้านบนแสดงผลลัพธ์ปัจจุบันที่ดีที่สุดที่พบในแต่ละรอบซ้ำ ตัวเลขผลลัพธ์สุดท้ายคือคำตอบ การสลับจากการประมวลผลจากด้านล่างซ้ายแทนด้านล่างขวาและการ0จัดทำดัชนีลดโซลูชันนี้ด้วยอักขระ 10 (!)
การสลับไปที่ c ++ จะลดการส่งโดยตัวละครมากกว่าหนึ่งตัวที่std::cout<<สั้นกว่าputchar(-48)และควรสนับสนุนมากกว่า 9 แท่งด้วยเอาต์พุตที่เหมาะสม (แม้ว่ามันอาจจะยากที่จะแยกแยะความแตกต่างในแต่ละเอาต์พุต)
การเอาฟิลด์คำตอบออก ตอนนี้จะส่งออกเฉพาะกระแสที่ดีที่สุดเมื่อมันเลื่อนขึ้นซึ่งจะตัดเอาท์พุทบางอย่างออกอย่างน้อย
ขณะนี้ไฟล์ทั้งหมดมีขนาดเพียง 78 ไบต์ - เมื่อเข้าใกล้ฟังก์ชั่นการแก้ปัญหาเท่านั้นCการส่งใช้ (พร้อมรหัสพิเศษมากมายเพื่อรองรับฟังก์ชั่นที่กล่าวมา)

คำอธิบายด้านล่างล้าสมัย:

cis global ดังนั้นเริ่มต้นได้ด้วย0
rคือจำนวนอินพุต (แถว) +1 (ชื่อของโปรแกรม)
vคืออาร์เรย์ของสตริงv[0]ที่ไม่ถูกต้อง (ชื่อของโปรแกรม)
เนื่องจากเป็น 0 ที่จัดทำดัชนีrอยู่นอกขอบเขตดังนั้นการลดลง
ในขณะที่r!=0(ชี้ไปที่สตริงที่ถูกต้อง) และอักขระcในสตริงไม่ใช่ตัวยกเลิก null '\0'
หากอักขระไม่ใช่ '0'
ขึ้นไปบนแถว ( r) และส่งออกคอลัมน์ ( c)
ไปที่คอลัมน์ถัดไป ( c)

เสร็จแล้ว

ฉันสามารถเล่นกอล์ฟนี้ต่อไปได้หรือไม่?

โค้ดที่ไม่ได้รับการแก้ไข (พร้อมเอาต์พุตพิเศษ):

#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[])
{
  int rows = argc-1;
  int cols = strlen(argv[1]);
  int ans;

  printf("rows: %d, cols: %d\n",rows, cols);

  while((rows)&&cols)
  {
    if (argv[rows][cols-1]-'0')
    {
      printf("stick @%d,%d\n",cols,rows);
      ans = cols;
      rows--;
    }
    else
    {
      printf("no stick @%d,%d\n",cols,rows);
      cols--;
    }
  }
  printf("%d",ans);
}
มันใช้ความยาวของสตริงเพื่อหาจำนวนคอลัมน์และ argc เพื่อหาจำนวนแถว เริ่มต้นที่มุมล่างขวามันเป็นไปตามกฎง่ายๆเหล่านี้: หากเซลล์เป็นแท่งแล้วเลื่อนขึ้นให้ตั้งคำตอบเป็นคอลัมน์ปัจจุบัน หากเซลล์ไม่ใช่ไม้ให้เลื่อนไปทางซ้าย O (n + m): เมื่อมันขยับขึ้นและไปทางซ้ายเท่านั้นมันก็สามารถอ่านได้สูงสุด n + m มันออกเร็ว แต่ถ้าตกลงด้านบนหรือด้านซ้ายของอาร์เรย์


1

OCaml - 144 ตัวอักษร

let s a=Array.(let rec f i j m=if i=0then m else if a.(i).(j)=0then if j=length a.(i)-1then m else f i(j+1)m else f(i-1)j j in f(length a-1)0 0)

ใช้เวลาint array arrayเป็น input และเริ่มต้นจากด้านล่างซ้ายขยับขึ้นหรือขวาถ้ามันเห็นหรือ1 จำนวนคอลัมน์เริ่มต้นที่00

การใช้

 s [| [| 0; 0; 0; 0 |]; [| 0; 0; 1; 0|]; [| 1; 0; 1; 0 |]; [| 1; 1; 1; 0 |]; [| 1; 1; 1; 1 |] |];;
 - : int = 2

Ungolfed

let s a = Array.(
  let rec f i j m = (* m is the longest stick seen so far *)
    if i=0 then m (* A column is full: this is the longest possible stick and j=m anyway *)
    else if a.(i).(j)=0 then (* current column is shorter than a previously seen stick *)
      if j=length a.(i)-1 then m (* we have examined all columns, just return m *)
      else f i(j+1) m (* start examining next column *)
    else f (i-1) j j (* current column is longer than all the ones previously seen. Check how long the stick is *)
  in
  f (length a-1) 0 0)

0

T-SQL - 71 64

ใช้ตาราง A เป็นอินพุต

SELECT IDENTITY(INT, 1, 1) R, A INTO A
FROM (VALUES
 ('0000')
,('1000')
,('1101')
,('1111')
) AS A(A)

และแบบสอบถามก็คือ

SELECT TOP(1)CHARINDEX('1',A)FROM A WHERE A LIKE'%1%' ORDER BY R

SQLFiddle

ส่งคืนแถวแรกจากตารางที่เรียงลำดับโดย r โดยที่มี 1 ในสตริง a

TOP(1) จำกัด ผลลัพธ์ไว้ที่แถวแรกที่ส่งคืน

CHARINDEX('1',A) ส่งคืนตำแหน่งของ 1 แรกในสตริงหรือศูนย์หากไม่พบ

WHERE A LIKE'%1%' ตัวกรองไปยังแถวที่ A ประกอบด้วย 1

ORDER BY R ตรวจสอบให้แน่ใจว่ามีการอ่านตารางจากบนลงล่าง


คุณสามารถอธิบายสิ่งที่เกิดขึ้นในรหัสนั้นได้หรือไม่ : D ไม่มีประสบการณ์กับ T-SQL
เครื่องมือเพิ่มประสิทธิภาพ

ฉันเห็นแล้วการกรองในแต่ละแถวไม่ได้เป็นการดำเนินการ O (n * m) ใช่ไหม นั่นคือไม่ซับซ้อนเวลาเชิงเส้น
เครื่องมือเพิ่มประสิทธิภาพ

ยากที่จะพูด โปรแกรม SQL จะตรวจสอบแถวทั้งหมดสำหรับ 1 ในคอลัมน์ จะส่งกลับเฉพาะแถวแรกจากบนลงล่างที่ผ่านการรับรอง ดังนั้นในสถานการณ์นี้มันจะสแกนทั้งตาราง กรองแถวด้วยคอลัมน์ที่มี 1 เรียงลำดับผลลัพธ์ในคอลัมน์ข้อมูลประจำตัวและส่งกลับผลลัพธ์แรก
MickyT

ดูมันเช่นนี้: จะเป็นอย่างไรถ้าแถวของคุณเป็นแบบ "0000", "0000", "0000", "0001" ในกรณีนี้มันจะต้องไปจนถึงแถวสุดท้ายและจนถึงอักขระสุดท้ายของแถวเพื่อหาว่ามี 1
เครื่องมือเพิ่มประสิทธิภาพ

1
ดังนั้นใช่แล้วมันคือ O (m * n) จากนั้น :)
เครื่องมือเพิ่มประสิทธิภาพ

0

Delphi 122 chars

เฮ้อ ... มันเป็นภาษาที่ใหญ่โต

อัปเดต: ต้องเพิ่ม 6 ตัวอักษรในฟังก์ชั่นการเปลี่ยนประเภทส่งคืนจาก I เป็นจำนวนเต็ม ฟังก์ชันยังคงถูกคอมไพล์เนื่องจากโปรแกรมทดสอบมี "type I = จำนวนเต็ม" คำสั่งที่เหลือจากโปรแกรมรุ่นก่อนหน้า

function S(A:array of string):integer;var n,c:integer;begin n:=0; repeat c:=Pos('1',A[n]);inc(n) until c>0; result:=c;end;

คุณกำลังเรียก Pos () ในแต่ละแถว (ในกรณีของคุณ, สตริง) ของ Array หรือไม่?
เครื่องมือเพิ่มประสิทธิภาพ

@Optimiser ใช่โปรแกรมค้นหาแต่ละสตริงในอาร์เรย์ (ใช้ 'inc (n)') จนกว่าจะพบ '1' พบ '1' แรกจะสูงสุด (หรือเท่ากับสูงสุด) '1' ดังนั้นตำแหน่งในสตริง (สตริงเป็น 1-ndexed ใน delphi) จะเป็นตำแหน่งของคอลัมน์ที่ยาวที่สุด งานประจำล้มเหลวหากไม่มี '1 อยู่ในอาร์เรย์ แต่ฉันเชื่อว่าสิ่งนี้จะขาดการป้อนข้อมูลเพราะจะไม่มี "แท่งที่ยาวที่สุด" ที่จะพบ
Penguino

1
อย่างแรกเลยนี่คืออินพุตที่ถูกต้อง: "0000", "0010", "1111"ประการที่สองคำตอบของคุณไม่ตรงกับความต้องการความซับซ้อนของเวลาเชิงเส้น
เครื่องมือเพิ่มประสิทธิภาพ

@Optimizer ใช่ว่าจะเป็นอินพุตที่ถูกต้องและระบุแท่งที่ 3 ได้อย่างถูกต้อง แต่ฉันรู้หลังจากทำการโพสต์ว่าฉันได้แปลงโปรแกรมคำสั่ง N ที่ถูกต้องซึ่งใช้อาร์เรย์เป็นโปรแกรมที่ไม่ถูกต้องในการสั่งซื้อ N ^ 2 ที่ใช้สตริง (ไล่การลดลงจาก ~ 160 ตัวอักษร)
Penguino

0

โครงการ - 236 ตัวอักษร

แม้จะยาวกว่ารุ่นเดลฟาย ... อาจมีวิธีที่จะทำสิ่งนี้ได้อย่างมีประสิทธิภาพมากขึ้นด้วยรูปแบบ และยิ่งแย่ลง - ฉันเพิ่งสังเกตเห็นว่ามันเป็นคำสั่ง m * n

(define (s l) (cond ((eq? (cdr l) '()) (car l)) (else (map + (car l) (s (cdr l)))))) (define (u l) (define (t n p q l) (cond ((eq? l '()) p) ((< n (car l)) (t (car l) q (+ 1 q) (cdr l))) (else (t n p (+ 1 q) (cdr l))))) (t 0 0 1 (s l)))

l คือรายการของฟอร์ม '((0 0 0 0) (1 0 0 0) (1 1 0 1) (1 1 1 1)) ฉันคิดว่านั่นเป็นตัวแทนที่ยุติธรรมของอินพุตอาร์เรย์ 2 มิติสำหรับโครงร่าง

(sl) รวมองค์ประกอบที่ n ของแต่ละรายการย่อยของรายการของรายการของ nuimbers ดังนั้น (s '((0 0 0 0) (1 0 0 0) (1 1 0 1) (1 1 1 1))) จะกลับมา (3 2 1 2)

(ul) ส่งคืน 'ดัชนี' ของรายการตัวเลขที่ใหญ่ที่สุด (ใช้ฟังก์ชันตัวช่วย t) ดังนั้น (u '(3 2 1 2)) จะส่งคืน 1 (เป็นองค์ประกอบที่ใหญ่ที่สุด' 3 ในรายการ ' (3 2 1 2) อยู่ที่ตำแหน่ง 1)


การรวมรายการย่อยทั้งหมดเป็นการดำเนินการ O (m * n)
Martin Ender

0

แร็กเก็ต 70

แข็งแรงเล่นกอล์ฟ:

(define(h m)(for/last([r m]#:final(memv 1 r))(length(takef r even?))))

สมมติว่าอินพุตเป็นอาร์เรย์สองมิติซึ่งใน Racket จะเป็นรายการของรายการ:

(define m 
  '((0 0 0 0)
    (1 0 0 0)
    (1 1 0 1)
    (1 1 1 1)))

Ungolfed:

(define (h m)
  ;; step through rows, stopping at the first that contains a 1
  (for/last ([r m] #:final (memv 1 r)) 
    (length (takef r even?)))) ; pop off the leading zeroes to get the column index

ส่งคืนดัชนีคอลัมน์ด้วยแท่งที่ยาวที่สุด


ดังนั้นโดยทั่วไปคุณจะผ่านแต่ละคอลัมน์และนับจำนวนของ1?
เครื่องมือเพิ่มประสิทธิภาพ

ฉันเห็นประเด็นของคุณ อัปเดตอัลกอริทึมแล้ว
Matthew Butterick

สิ่งนี้ยังคงมีความซับซ้อนของกรณีที่แย่ที่สุดของ O (m * n) (สำหรับกรณีที่ไม่มี1ในเมทริกซ์หรือเฉพาะในแถวล่าง)
Martin Ender


0

JavaScript ES6, 65 ไบต์

ใช้รูปแบบอินพุตทั้งสอง

f=(a,t)=>a.reduceRight((p,c)=>t+1?t:(x=c.indexOf(1,p))+1?x:t=p,0)

อธิบาย:

วนซ้ำจากล่างขึ้นบน ใช้String.prototype.indexOf()หรือArray.prototype.indexOf()ขึ้นอยู่กับอินพุตในแต่ละค่า ค้นหาดัชนีแรกของแต่ละแถวด้วย 1 จากออฟเซ็ตก่อนหน้าหากพบว่าไม่มีใครเลยมันจะตั้งค่าtตัวแปรเป็นออฟเซ็ตสุดท้ายและจะไม่ทำการindexOfเรียกอีกต่อไป


indexOfทำงานได้ทั้งO(log n)หรือO(n)ดังนั้นอัลกอริทึมโดยรวมจะไม่อยู่ในO(m + n)
เครื่องมือเพิ่มประสิทธิภาพ

@Optimizer ใช่รู้ว่ามันเป็น O (m * n) ไม่ได้คิดตรง
George Reith

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