แก้ปริศนาสี


35

ที่เพื่อนของเราที่Puzzling.SEปริศนาต่อไปนี้ถูกโพสต์: ปริศนาสีนี้สามารถแก้ไขได้เสมอหรือไม่? โดยเอ็ดการ์กรัมคุณสามารถเล่นได้ที่นี่

คำอธิบายปริศนา

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

ปริศนาสามสี 8x8

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

อินพุตและเอาต์พุต

การป้อนข้อมูลจะเป็นm x nเมทริกซ์ประกอบด้วยจำนวนเต็ม1, 2และ3(หรือ0, 1, 2ถ้าสะดวก) คุณสามารถรับอินพุตนี้ในรูปแบบใด ๆ ก็ได้ ทั้งสองmและnมี>1และไม่หารด้วย 3. คุณอาจจะสมมติปริศนาไม่ได้แก้ไข

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

อัลกอริทึมของคุณควรทำงานภายในเวลาที่เหมาะสมในกรณี 8x8 ดั้งเดิม เดรัจฉานบังคับให้มันสมบูรณ์ไม่ได้รับอนุญาตอย่างชัดเจนเช่นอัลกอริทึมของคุณควรทำงานภายใต้O(k^[m*(n-1)+(m-1)*n])กับkจำนวนของขั้นตอนที่จำเป็นสำหรับการแก้ปัญหา วิธีการแก้ปัญหาไม่จำเป็นต้องดีที่สุด หลักฐานที่ให้ไว้ในคำถามที่เชื่อมโยงอาจทำให้คุณมีความคิดเกี่ยวกับวิธีการทำสิ่งนี้ (เช่นก่อนอื่นให้ทำคอลัมน์ทั้งหมดโดยใช้แผ่นกระเบื้องที่อยู่ติดกันในแนวตั้งจากนั้นทำทุกแถว)

กรณีทดสอบ

ในกรณีทดสอบเหล่านี้พิกัดที่ใช้ 1 และแถวจะถูกจัดทำดัชนีก่อน (เช่น MATLAB / Octave และอื่น ๆ อีกมากมาย)

Input: 
[1 2]
Output: (result: all 3's)
[1 1],[1,2]


Input:
[ 1 2
  3 1 ]
Output: (result: all 1's)
[1 1],[2 1]        (turn left column into 2's)
[2 1],[2 2]        (turn right column into 3's)
[1 1],[1 2]        (turn top row into 1's)
[2 1],[2 2]        (turn bottom row into 1's)

Input:
[1 2 3 2
 3 2 1 1]

Output: (result: all 3's)
[1 1],[1 2] 
[1 3],[1 4] 
[1 2],[1 3] 
[1 1],[1 2] 
[1 2],[1 3] 
[1 1],[1 2]
[1 3],[1 4]
[2 1],[2 2]
[1 1],[2 1]
[1 2],[2 2]
[1 3],[2 3]
[1 4],[2 4]

หากต้องการฉันอาจโพสต์ pastebin ของกรณีทดสอบที่ใหญ่กว่า แต่ฉันคิดว่ามันน่าจะเพียงพอ


ฉันชอบที่จะเห็นเวอร์ชันการท้าทายของโค้ดซึ่งเป้าหมายคือการไขปริศนาด้วยการเคลื่อนไหวน้อยที่สุด
Mego

@ ฉันคิดว่าอย่างนี้แน่นอน อย่างไรก็ตามฉันกลัวว่าสิ่งนี้จะกลายเป็น DFS หรือ BFS ซึ่งจะใช้เวลาตลอดไปในการทำงาน หรือเพื่อป้องกันสิ่งนี้ชุดของข้อ จำกัด ที่คลุมเครือ (เช่น 'ต้องทำงานภายในหนึ่งชั่วโมง' ซึ่งเป็นที่โปรดปรานของผู้คนที่มีคอมพิวเตอร์ขนาดใหญ่หรือต้องการให้ฉันทดสอบวิธีแก้ปัญหาทั้งหมด) และยิ่งกว่านั้นความท้าทายในปัจจุบันไม่มีคำตอบให้ฉันเลยสงสัยว่ารุ่นที่ยากยิ่งกว่านั้นต้องใช้ฮิวริสติก ฯลฯ จะพิสูจน์ว่าเป็นที่นิยมมากขึ้น ... แต่บางทีถ้าความท้าทายนี้หยิบโมเมนตัมฉันอาจโพสต์ความท้าทายพี่น้อง อธิบาย.
Sanchises

ฉันคิดว่าฉันจะพยายามทำสิ่งนั้นใน Lua แต่อาจนานกว่าโซลูชัน 324 Bytes ของคุณ ^^
Katenkyo

@Katenkyo ทางเดียวเท่านั้นที่จะหา! ฉันรอคอยที่จะเห็นทางออกของคุณ
Sanchises

คุณจะต้องรอนิดหน่อยเศร้าคุณป้องกันการแก้ปัญหาสัตว์เดรัจฉานบังคับดังนั้นฉันต้องหาวิธีแก้ปัญหาที่สั้นใน lua: p
Katenkyo

คำตอบ:


5

Ruby, 266 ไบต์

มากกว่าหรือน้อยกว่าเพียงแค่พอร์ตของโซลูชัน Octave ยกเว้นจะแก้ไขแถวก่อนแทนที่จะเป็นคอลัมน์ อินพุตคืออาร์เรย์ของอาร์เรย์โดยที่อาร์เรย์ภายในเป็นแถว [row, column, row, column]การส่งออกมีการเคลื่อนไหว ชุดทดสอบ

->m{t=->v{v.size*v.inject(:+)%3}
s=->a,x,r{g=t[a]
(q=(r=0..a.size-2).find{|i|a[i]!=a[i+1]&&g!=a[i]}||r.find{|i|a[i]!=a[i+1]}
a[q,2]=[t[a[q,2]]]*2
p r ?[x,q,x,q+1]:[q,x,q+1,x])while[]!=a-[g]}
m.size.times{|i|s[m[i],i,1]}
m=m.shift.zip *m
m.size.times{|i|s[m[i],i,p]}}

ไม่พอใจกับคำอธิบาย

->m{                                  # Start lambda function, argument `m`
  t=->v{v.size*v.inject(:+)%3}        # Target color function
  s=->a,x,r{                          # Function to determine proper moves
                                      #   a = row array, x = row index, r = horizontal
    g=t[a]                            # Obtain target color
    (
      q=(r=0..a.size-2).find{|i|      # Find the first index `i` from 0 to a.size-2 where...
        a[i]!=a[i+1]                  # ...that element at `i` is different from the next...
        &&g!=a[i]                     # ...and it is not the same as the target color
      } || r.find{|i|a[i]!=a[i+1]}    # If none found just find for different colors
      a[q,2]=[t[a[q,2]]]*2            # Do the color flipping operation
      p r ?[x,q,x,q+1]:[q,x,q+1,x]    # Print the next move based on if `r` is truthy
    ) while[]!=a-[g]}                 # While row is not all the same target color, repeat
m.size.times{|i|                      # For each index `i` within the matrix's rows...
  s[m[i],i,1]                         # ...run the solving function on that row
                                      #   (`r` is truthy so the moves printed are for rows)
}
m=m.shift.zip *m                      # Dark magic to transpose the matrix
m.size.times{|i|s[m[i],i,p]}}         # Run the solving function on all the columns now
                                      #   (`r` is falsy so the moves printed are for columns)

น่าสนใจที่จะเห็นว่าพอร์ตระหว่างภาษาที่ไม่ใช่กอล์ฟสองภาษายังคงสามารถสร้างความแตกต่าง ~ 20% คุณอาจจะสามารถเพิ่มคำอธิบายสั้น ๆ (โดยเฉพาะสายที่ 3 - ฉันแอบหวังว่าผมจะสามารถใช้ในคำตอบของฉันตั้งแต่? intersectเป็นเช่นคำหลักขนาดใหญ่)
Sanchises

@sanchises คำอธิบายถูกเพิ่มเข้ามา เกี่ยวกับintersectฉันไม่ทราบว่าคุณสามารถแก้ไขได้ว่าวิธีการทำงานของฉันเป็นเพราะทับทิมfindทำงานในหน้าที่และfunctionคำหลักของคุณเป็นใหญ่
หมึกมูลค่า

ฉันยังใช้วิธีการของคุณได้find- ขอบคุณ! แต่ถึงกระนั้นก็ยังไม่มีที่ไหนที่ใกล้จะเอาชนะคุณ ...
Sanchises

13

อ็อกเทฟ334 313 ไบต์

เนื่องจากความท้าทายอาจดูน่ากลัวฉันจึงนำเสนอทางออกของตัวเอง ฉันไม่ได้พิสูจน์อย่างเป็นทางการว่าวิธีนี้ใช้งานได้ (ฉันเดาว่าจะลงมาเพื่อพิสูจน์ว่าอัลกอริทึมจะไม่ติดอยู่ในลูป) แต่จนถึงตอนนี้มันใช้งานได้อย่างสมบูรณ์แบบโดยทำการทดสอบ 100x100 ภายใน 15 วินาที โปรดทราบว่าฉันเลือกที่จะใช้ฟังก์ชั่นที่มีผลข้างเคียงมากกว่าที่จะส่งกลับพิกัดทั้งหมดตั้งแต่ที่บันทึกไว้ฉันไม่กี่ไบต์ พิกัดอยู่แถวเมเจอร์ 1-based row1 col1 row2 col2และจัดรูปแบบเป็น สีขาเข้ามี0,1,2ตั้งแต่นี้ทำงานได้ดีขึ้นด้วยmodค่าใช้จ่ายของการมีการใช้มากกว่าnumel nnzรุ่นที่ตีกอล์ฟ: แก้ไข: บันทึกอีกสองสามไบต์โดยใช้เทคนิคจากคำตอบของ Kevin Lau

function P(p)
k=0;[m,n]=size(p);t=@(v)mod(sum(v)*numel(v),3);for c=1:n
p(:,c)=V(p(:,c));end
k=1;for r=1:m
p(r,:)=V(p(r,:));end
function a=V(a)
while any(a-(g=t(a)))
isempty(q=find(diff(a)&a(1:end-1)-g,1))&&(q=find(diff(a),1));
a([q q+1])=t(a([q q+1]));if k
disp([r q r q+1])
else
disp([q c q+1 c])
end;end;end;end

ตัวอย่าง GIF ของอัลกอริทึมการแก้:

ป้อนคำอธิบายรูปภาพที่นี่

เวอร์ชันที่ไม่ถูกปรับแต่ง:

function solveChromaticPuzzle(p)
[m,n]=size(p);                           % Get size
t=@(v)mod(sum(v)*numel(v),3);            % Target colour function
for c=1:n                                % Loop over columns
    p(:,c)=solveVec(p(:,c));             % Solve vector
end
for r=1:m                                % Loop over rows
    p(r,:)=solveVec(p(r,:));
end
    function a=solveVec(a)               % Nested function to get globals
        g=t(a);                          % Determine target colour
        while(any(a~=g))                 % While any is diff from target...
            % Do the finding magic. Working left-to-right, we find the
            % first pair that can be flipped (nonzero diff) that does not
            % have the left colour different from our goal colour
            q=min(intersect(find(diff(a)),find(a~=g)));
            if(isempty(q))               % In case we get stuck...
                q=find(diff(a),1);       % ... just flip the first possible
            end;
            a([q q+1])=t(a([q q+1]));    % Do the actual flipping.
            if(exist('r'))               % If we're working per row
                disp([r q r q+1])        % Print the pair, using global row
            else
                disp([q c q+1 c])        % Print the pari, using global col
            end
        end
    end
end

เพิ่งสังเกตเห็น แต่ชื่อของฉันไม่ใช่ Kenny Lau ... นั่นคือผู้ใช้รายอื่นและชื่อผู้ใช้ของฉันระบุว่าฉันไม่ใช่ Kenny
Value Ink

7

Lua, 594 575 559 Bytes

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

ฉันจะให้คำอธิบายแบบเต็มเมื่อฉันทำเสร็จแล้ว

function f(t)s=#t a=","for i=1,s do p=t[i]for i=1,s
do p.Q=p.Q and p.Q+p[i]or p[i]end p.Q=(p.Q*#p)%3 for i=1,s do for j=1,#p-1 do
x=p[j]y=p[j+1]u=x~=y and(p.S and p.R==p.S or x~=p.Q)v=(x+y)*2p[j]=u and v%3or x
p[j+1]=u and v%3or y print(i..a..j,i..a..j+1)end
p.R=p.S p.S=table.concat(p)end end
for i=1,s do Q=Q and Q+t[i][1]or t[i][1]end Q=(Q*s)%3 for i=1,s
do for j=1,s-1 do p=t[j]q=t[j+1]x=p[1]y=q[1]u=x~=y and(S and R==S or x~=Q)v=(x+y)*2
for k=1,#p do p[k]=u and v%3or x q[k]=u and v%3or y
print(j..a..k,j+1..a..k)end Y=Y and Y..x or x end
R=S S=Y end end

5

สนิม496 495 ไบต์

น่าเศร้าที่ฉันไม่สามารถเอาชนะ OP แต่สำหรับคำตอบสนิมฉันค่อนข้างพอใจกับจำนวน bytecount

let s=|mut v:Vec<_>,c|{
let p=|v:&mut[_],f,t|{
let x=|v:&mut[_],i|{
let n=v[i]^v[i+1];v[i]=n;v[i+1]=n;
for k in f..t+1{print!("{:?}",if f==t{(k,i,k,i+1)}else{(i,k,i+1,k)});}};
let l=v.len();let t=(1..4).find(|x|l*x)%3==v.iter().fold(0,|a,b|a+b)%3).unwrap();
let mut i=0;while i<l{let c=v[i];if c==t{i+=1;}else if c==v[i+1]{
let j=if let Some(x)=(i+1..l).find(|j|v[j+1]!=c){x}else{i-=1;i};x(v,j);}else{x(v,i);}}t};
p(&mut (0..).zip(v.chunks_mut(c)).map(|(i,x)|{p(x,i,i)}).collect::<Vec<_>>(),0,c-1usize)};

อินพุต:เวกเตอร์ของตัวเลขรวมถึงจำนวนคอลัมน์ เช่น

s(vec!{1,2,1,3},2);

เอาท์พุท

 (row1,col1,row2,col2)

ไปยังบรรทัดคำสั่ง

ฉันจะแก้ไขทุก ๆ แถวก่อนแล้วจึงแก้ไขคอลัมน์ผลลัพธ์เพียงครั้งเดียว แต่พิมพ์ขั้นตอนสำหรับคอลัมน์ทั้งหมด ดังนั้นมันจึงค่อนข้างมีประสิทธิภาพ :-P

ด้วยการกำหนด:

let s=|mut v:Vec<_>,c|{  
    let p=|v:&mut[_],f,t|{     // solves a single row/column
        let x=|v:&mut[_],i|{   // makes a move and prints it 
            let n=v[i]^v[i+1]; // use xor to calculate the new color
            v[i]=n;
            v[i+1]=n;
            for k in f..t{
                print!("{:?}",if f==t{(k,i,k,i+1)}else{(i,k,i+1,k)});
            }
        };
        let l=v.len();
        // find target color
        // oh man i am so looking forward to sum() being stabilized
        let t=(1..4).find(|x|(l*x)%3==v.iter().fold(0,|a,b|a+b)%3).unwrap();
        let mut i=0;
        while i<l{
            let c=v[i];
            if c==t{             // if the color is target color move on
                i+=1;
            }else if c==v[i+1]{ // if the next color is the same
                                // find the next possible move
                let j=if let Some(x)=(i+1..l).find(|j|v[j+1]!=c){x}else{i-=1;i};
                x(v,j);
            }else{              // colors are different so we can make a move
                x(v,i);         
            }
        }
        t
    };
    // first solve all rows and than sovle the resulting column c times 
    p(&mut (0..).zip(v.chunks_mut(c)).map(|(i,x)|p(x,i,i)).collect::<Vec<_>>(),0,c-1usize)
};

แก้ไข: ตอนนี้ส่งคืนสีของโซลูชันซึ่งช่วยอัฒภาคให้ฉัน ^^


5

Befunge , 197 368 696 754 Bytes


(ใช่ฉันกำลังเล่นกอล์ฟรหัสย้อนกลับยิ่งดีเท่าไร)


ฉันคิดว่ามันอาจเป็นความท้าทายในการเขียนอัลกอริทึมนี้ใน Befunge และมันอาจสนุก

ฉันอยากให้มันเป็นโครงการชุมชนดังนั้นหากใครต้องการที่จะทำงานกับมันโปรดทำเช่นนั้น

ในตอนท้ายฉันทำทุกอย่างตามลำพังดังนั้นฉันจะทำเองให้เสร็จ (เกือบเสร็จแล้ว)


ยังทำอะไรอยู่: โค้ดรูปหมุนรอบ

&:19p&:09p:v:p94g92g90  <
 v94+1:g94&_$59g1+59p1-:|
 >p59gp1-: ^    vp95g93$<
v94\-1<v:g<     >  v
>g:1+v^_$v^90p94g92<
v5p94<   3>1+59p   ^
>9gg+\:^ %g   v93:g95<           v3_2         v
v1pg95g94<^95<>g-v>$v^           v ^-%3*2\gg9<
>9g39g+59g-1-|v-1_^ #^pg95+g92g90<1_09g:29g+5^
       ;  >  >  09g:29g+59gg\3%-# !^v         <
          ^p95<                  ^  <
     v  p96-1+g90g92<
     v                  p95_@
            >59g1+:39g-19g-^
     v    >p 79g:59gg\1+59gp$$$$$29g49pv
    > p59g^ |<<<<<<<<<<<<<<<<<<!-g96g94<
>:79^>29g49p>69g1+59gg49g:59gg\1+49p- v
^\-\6+gg95+1\g< v         !-g96:<-1g94_^
>"]",52*,::59g^v_::1+59gg\59gg-v^ <
^ .-g93g95,.-g<>:69g- v  v-g96:_1+^
>+" [,]",,,\29^       >#v_$:49g2-v
^1:.-g93g95,.-g92\,"[ ":<        <

(ใช่มันเป็นโทรลล์เชื่อฉัน)


โดยพื้นฐานแล้วมันจะอ่านอาเรย์และคำนวณการย้ายที่ต้องทำเพื่อแก้ปัญหาแถวโดยให้อินพุตเป็น

(number of rows) (number of columns) 1 2 3 1 1 3 2 1 2 ....

(อาร์เรย์ทั้งหมดถูกส่งผ่านเป็นรายการ [row1, row2, row3, …])

ผลลัพธ์คือ

[col row],[col',row']
[col2 row2],[col2',row2']
...

แถวและคอลัมน์ทั้งคู่เริ่มต้นที่ 0


ตอนนี้แถวได้รับการแก้ไขมันใกล้จะเสร็จแล้ว! ไชโย!


คำอธิบาย: (จะอัปเดตในภายหลัง)

ภาพ

ดังนั้นจึงมี 5 ส่วนหลัก:

  • บรรทัดแรกเป็นสีเขียวอ่านบรรทัดอินพุตและเขียนหนึ่งแถวของอาร์เรย์
  • อันที่สองในสีส้มส่งผ่านไปยังแถวถัดไปของอาร์เรย์
  • ที่สามในสีฟ้าผลรวมแถว
  • อันที่สี่สีชมพูร้อนใช้โมดูลัส 3 ของผลรวมบันทึกที่ด้านขวาของแถวที่เกี่ยวข้องและไปที่แถวถัดไป
  • สุดท้ายในสีแดงส่วนที่คำนวณสีเป้าหมายจากหมายเลขที่คำนวณก่อนหน้านี้ ส่วนนี้โง่จริง ๆ และน่าจะเขียนใหม่ แต่ฉันไม่ได้คิดออกว่าจะทำอย่างนั้นได้อย่างไร (ผ่านจาก 197 ไบต์ไปจนถึง 368 ด้วยส่วนนั้น)

ส่วนสีเทาคือการเริ่มต้น


นี่คือคำอธิบายที่ลึกซึ้งยิ่งขึ้นของโมดูลที่ค้นหากล่องถึงการรวม (ซึ่งเขียนไว้ที่นี่โดยวิธี)

                                       B
            @                          v
            |                  !-g96g94<
ENTRY>29g49p>69g1+59gg49g:59gg\1+49p- v
                v         !-g96:<-1g94_^
               v_::1+59gg\59gg-v^ <
               >:69g- v  v-g96:_1+^
                      >#v_$:49g2-v
                    CALL<        <

ส่วนที่เรียกคือเมื่อตัวชี้คำสั่งไปยังโมดูลอื่นเพื่อรวมเข้ากับกล่อง มันกลับมาที่โมดูลนี้ผ่านทางรายการ 'B'

นี่คือรหัสเทียมบางตัว: (currentx เกี่ยวข้องกับการอ่านอาร์เรย์) สำหรับ:

    69g1+59gg  // read target color
    49g:59gg\1+49p // read current color and THEN shift the currentx to the next box
    if ( top != top ){  // if the current color is bad
        49g1-          //  put the current place  (or currentx - 1) in the stack
        While:
            if ( :top != 69g ){   // if you didn't reach the end of the list
                ::1+              // copy twice, add 1
                if ( 59gg == \59gg ){ // if the next color is the same than current
                   1+                // iterate
                   break While;
                }
            }

        : // copies j (the previous raw iterator)
        if ( top == 69g ){  // if you reached the end of the row (which mean you can't swap with the color after that point)
            $:              // discard j's copy and copy target
            49g2-           // put the place just before the color change on the stack
            combine_with_next;
        } else {
            combine_with_next;
        }
        29g49p   // back to the beginning of the row (there was some changes int the row)
    }

    if ( 49g != 69g ) // if you didn't reach the end of the list
        break For:

โปรดทราบว่าหากคุณต้องการทดสอบคุณจะต้องใส่ช่องว่างต่อท้ายและลากเส้นขึ้นบรรทัดใหม่เพื่อให้มีพื้นที่เพียงพอในการจัดเก็บอาร์เรย์ถ้าคุณต้องการใช้ตีความฉันเชื่อมโยง 22 + จำนวนแถวในอินพุตเป็นบรรทัดต่อท้ายและ 34 + จำนวนคอลัมน์เป็นช่องว่างต่อท้ายในหนึ่งบรรทัดควรเป็น ok


แค่สงสัยว่าทำไมสิ่งนี้ถึงไม่ใช่การแข่งขัน?
Value Ink

เนื่องจากส่วนนี้: 'ฉันต้องการให้เป็นโครงการชุมชน' ฉันคิดว่าฉันคงเป็นคนขี้โกงอย่างอื่น
Maliafo

ฉันมีผลลัพธ์ของ 197 Bytes คุณทำงานภายใต้ windows หรือไม่? (และนับ\r\nแทน\nเท่านั้น?)
Katenkyo

หืมมมฉันเดาว่าฉันจะคัดลอกบางส่วนที่เหลือเมื่อนับจำนวนไบต์ขอบคุณ
Maliafo

หากในตอนท้ายฉันเป็นคนเดียวที่ทำมันฉันจะลบการกล่าวถึง แต่ฉันหวังว่าฉันจะไม่
Maliafo

2

C, 404 ไบต์

รหัสกอล์ฟครั้งแรกของฉันฉันค่อนข้างมีความสุขกับการเปิด แม้ว่าจะใช้เวลานานเกินไป มันไม่ได้มาตรฐานอย่างสมบูรณ์ C ทุกอย่างจะรวบรวมภายใต้ gcc โดยไม่มีธงพิเศษ (และไม่สนใจคำเตือน) ดังนั้นจึงมีฟังก์ชั่นซ้อนอยู่ในนั้น ฟังก์ชั่นfใช้ขนาดmและnเป็นข้อโต้แย้งแรกและเป็นอาร์กิวเมนต์ที่สามใช้เวลา (ตัวชี้ int) ไปยังอาร์เรย์ที่มีขนาดm× n(จัดทำดัชนีโดยแถวแรก) อาร์กิวเมนต์อื่น ๆ เป็นอาร์กิวเมนต์ดัมมี่คุณไม่จำเป็นต้องผ่านมันเข้ามาเพื่อบันทึกไบต์ในการประกาศตัวแปร มันเขียนแต่ละคู่เปลี่ยนไปเป็น STDOUT ในรูปแบบที่row1,col1:row1,col1;มีเครื่องหมายอัฒภาคแยกคู่ ใช้การจัดทำดัชนีแบบ 0

#define A a[i*o+p
#define B A*c
f(m,n,a,i,j,o,p,b,c,d)int*a;{
int t(x){printf("%d,%d:%d,%d;",b?i:c+x,b?c+x:i,b?i:c+1+x,b?c+1+x:i);}
o=n;p=b=1;for(;~b;b--){
for(i=0;i<m;i++){c=j=0;
for(;j<n;)c+=A*j++];d=c*n%3;
for(j=0;j<n-1;j++) 
while(A*j]^d|A*j+p]^d){
for(c=j;B]==B+p];c++);
if(c<n-2&B]==d&2*(B+p]+A*(c+2)])%3==d)
B+p]=A*(c+2)]=d,t(1);else
B]=B+p]=2*(B]+B+p])%3,
t(0);}}o=m;p=m=n;n=o;o=1;}}

ฉันใช้อัลกอริทึมแตกต่างจาก OP เล็กน้อยสำหรับการแก้แต่ละแถว / คอลัมน์ มันไปบางอย่างเช่นนี้ (pseudocode):

for j in range [0, rowlength):
    while row[j] != targetCol or row[j+1] != targetCol:
        e=j
        while row[e] == row[e+1]:
            e++             //e will never go out of bounds
        if e<=rowLength-3 and row[e] == targetCol 
                and (row[e+1] != row[e+2] != targetCol):
            row.changeColor(e+1, e+2)
        else:
            row.changeColor(e, e+1)

การfor(;~b;b--)วนซ้ำจะดำเนินการสองครั้งอย่างแน่นอนในการผ่านครั้งที่สองจะเป็นการแก้ปัญหาคอลัมน์แทนที่จะเป็นแถว สิ่งนี้ทำได้โดยการสลับnและmและการเปลี่ยนค่าของoและpที่ใช้ในการคำนวณตัวชี้เพื่อที่อยู่อาร์เรย์

นี่คือรุ่นที่ไม่ได้รับการฝึกหัดพร้อมด้วยเมนทดสอบและพิมพ์อาเรย์ทั้งหมดหลังจากการเคลื่อนไหวทุกครั้ง (กด enter ไปยังขั้นตอนที่ 1 ถึง):

#define s(x,y)b?x:y,b?y:x
#define A a[i*o+p
#define B A*e
f(m,n,a,i,j,o,p,b,c,d,e)int*a;{

    int t(x){
        printf("%d,%d:%d,%d;\n",s(i,e+x),s(i,e+1+x));
        getchar();
        printf("\n");
        for(int i2=0;i2<(b?m:n);i2++){
            for(int j2=0;j2<(b?n:m);j2++){
                printf("%d ",a[i2*(b?n:m)+j2]);
            }
            printf("\n");
        }
        printf("\n");
    }

    printf("\n");
    b=1;
    for(int i2=0;i2<(b?m:n);i2++){
        for(int j2=0;j2<(b?n:m);j2++){
            printf("%d ",a[i2*(b?n:m)+j2]);
        }
        printf("\n");
    }
    printf("\n");

    o=n;p=1;
    for(b=1;~b;b--){
        for(i=0;i<m;i++){
            c=0;
            for(j=0;j<n;j++) c+= a[i*o+p*j];
            d=0;
            d = (c*n)%3;
            for(j=0;j<n-1;j++) {
                while(a[i*o+p*j]!=d||a[i*o+p*j+p]!=d){
                    for(e=j;a[i*o+p*e]==a[i*o+p*e+p];e++);
                    if(e<=n-3 && a[i*o+p*e]==d 
                            && 2*(a[i*o+p*e+p]+a[i*o+p*(e+2)])%3==d){
                        a[i*o+p*e+p]=a[i*o+p*(e+2)]=d;
                        t(1);
                    }else{
                        a[i*o+p*e]=a[i*o+p*e+p] = 2*(a[i*o+p*e]+a[i*o+p*e+p])%3;
                        t(0);
                    }
                }
            }
        }
        o=m;p=m=n;n=o;o=1;
    }
}

main(){
    int g[11][11] = 
    {
        {0,2,1,2,2,1,0,1,1,0,2},
        {2,1,1,0,1,1,2,0,2,1,0},
        {1,0,2,1,0,1,0,2,1,2,0},
        {0,0,2,1,2,0,1,2,0,0,1},
        {0,2,1,2,2,1,0,0,0,2,1},
        {2,1,1,0,1,1,2,1,0,0,2},
        {1,0,2,1,0,1,0,2,2,1,2},
        {0,0,2,1,2,0,1,0,1,2,0},
        {1,2,0,1,2,0,0,2,1,2,0},
        {2,1,1,0,1,1,2,1,0,0,2},
        {0,2,1,0,1,0,2,1,0,0,2},
    };
    #define M 4
    #define N 7
    int grid[M][N];
    for(int i=0;i<M;i++) {
        for(int j=0;j<N;j++) {
            grid[i][j] = g[i][j];
        }
    }
    f(M,N,grid[0],0,0,0,0,0,0,0,0);
};

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

1
ฉันคิดว่ามันน่าสนใจมากขึ้นเมื่อผู้คนคิดวิธีแก้ปัญหาที่แตกต่างกันออกไปและจากการทดสอบอย่างรวดเร็วฉันเดาว่าทั้งสองวิธีจะเหมือนกันในจำนวนไบต์ ฉันอาจลองอัลกอริทึมของคุณด้วยและดูว่าฉันจะลดลงได้ไหม
Norg74

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

การกล่าวถึงสัตว์เดรัจฉานนั้นหมายถึงการเพิ่มความเข้มงวดของคำพูด 'เวลาที่สมเหตุสมผล' ดังนั้นให้ดูเป็น t « O (... ) ฉันรู้ว่ามีพื้นที่สีเทาระหว่างแรงเดรัจฉานและอัลกอริธึมที่สมเหตุสมผลดังนั้นใช้วิจารณญาณของคุณเองว่าคุณรู้สึกว่ามันกำลังทำงานเพื่อไขปริศนาหรือถ้ามันเป็นการดัดแปลงเล็กน้อยใน DFS หรือ BFS ซึ่งเป็นผู้ไม่เชื่อเรื่องพระเจ้า .
Sanchises
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.