เลือกฆ่าจำนวนเต็มบวก


21

บทนำ

Arithmetic Gaol เป็นสิ่งอำนวยความสะดวกพิเศษที่คุมขังจำนวนเต็มบวก อย่างไรก็ตามเมื่อเร็ว ๆ นี้จำนวนเต็มบวกได้พยายามที่จะหลบหนี ดังนั้นผู้พิทักษ์จึงตัดสินใจที่จะกำจัดจำนวนเต็มบวกบางส่วนเพื่อส่งข้อความไปยังเลขจำนวนเต็มอื่น ๆ พวกเขาได้ว่าจ้างวิศวกรซอฟต์แวร์ให้เขียนโปรแกรมเพื่อคำนวณจำนวนเต็มที่จะกำจัดเพื่อให้ได้ผลสูงสุด

ป้อนคำอธิบาย

อินพุตถูกกำหนดผ่าน STDIN อาร์กิวเมนต์บรรทัดคำสั่งหรือฟังก์ชันอินพุตผู้ใช้ (เช่นraw_input) คุณไม่สามารถใช้เป็นอาร์กิวเมนต์ของฟังก์ชันหรือตัวแปรที่มีค่าเริ่มต้นได้ (เช่นโปรแกรมนี้ต้องการอินพุตในตัวแปรx)

บรรทัดแรกของการป้อนข้อมูลที่มีจำนวนเต็มบวกเดียวที่n 8 >= n >= 3ต่อไปนี้ที่มีnเส้นมีตัวจากชุดที่n [1,2,3,4,5,6,7,8,9]นี่คือตัวอย่างอินพุต:

5
22332
46351
65455
24463
65652

คำอธิบายผลลัพธ์

ผู้ดูแลต้องการกำจัดตัวเลขเพื่อให้เป็นไปตามเงื่อนไขต่อไปนี้:

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

เอาท์พุทอินพุท (ลบบรรทัดแรก) #โดยมีตัวเลขที่ตัดออกแทนที่ด้วย

อาจมีทางออกมากกว่าหนึ่งวิธี หากเป็นกรณีนี้คุณสามารถแก้ไขปัญหาได้

อาจไม่มีวิธีแก้ปัญหา no answerหากเป็นกรณีที่เอาท์พุทสตริง

นี่เป็นเอาต์พุตที่เป็นไปได้สำหรับอินพุตตัวอย่าง:

#2#3#
46351
6#4#5
24#63
#56#2

ตัวอย่างอินพุตและเอาต์พุต

มีเอาต์พุตหลายเอาต์พุตสำหรับแต่ละอินพุตดังนั้นเอาต์พุตเหล่านี้เป็นเพียงตัวอย่าง

การป้อนข้อมูล:

5
46551
51565
32654
14423
43244

เอาท์พุท:

46#51
#156#
326#4
1#423
#324#

การป้อนข้อมูล:

7
7183625
1681563
5238564
8786268
1545382
3814756
5325345

เอาท์พุท:

71#362#
#6815#3
5238#64
#7#62#8
154#382
3814756
#325#4#

การป้อนข้อมูล:

8
21534768
75196287
68392184
96244853
44865912
76516647
89751326
43698979

เอาท์พุท:

21#34768
#5196287
683#21#4
9#24#853
#4865912
7#51#64#
89751326
436#8#7#

การป้อนข้อมูล:

4
2222
2331
3112
1322

เอาท์พุท:

no answer

4
(หรือที่รู้จักในชื่อคนโสด )
Doorknob

ปริศนานี้ดีมาก ขอขอบคุณ. ทำงานเกี่ยวกับการแก้ปัญหา
ไม่ใช่ว่า Charles

1
ฉันชอบจิ๊กซอว์นี้ แต่ไม่สามารถตอบ "ตามสภาพ" โดยใช้ JavaScript ในเบราว์เซอร์เนื่องจากวิธีการป้อนข้อมูลผู้ใช้เพียงอย่างเดียวpromptไม่อนุญาตให้ใช้อินพุตแบบหลายบรรทัด
edc65

คำตอบ:


0

ทับทิม, 346 344 329 316 ไบต์, sl∞∞∞∞∞∞w

นี่คือโค้ดกอล์ฟไม่ใช่รหัสเร็วดังนั้น ...

N=/!/=~G=$*[1..-1]*?!
M=N*N
g=->i{(!G[i]||G[i]<?*||i<0||A[i])&&break
A[i]=0
[1,N+1,-1,-1-N].map{|a|g[i+a]}}
f=->w,a{A=[];g[/\d/=~G=a];/#.{#{N}}?#/!~G&&/(\d)([^!]*|.{#{N}}.{#{O=N+1}}*)\1/!~G&&A.count(0)+w==M&&N.times.map{|m|puts G[m*(1+N),N]}&&exit
(w...M).map{|j|b=a+'';b[j]=?#
w<M&&f[w+1,b]}}
f[0,G]
$><<"no answer"

ใช้มันเหมือน:

mad_gaksha@madlab ~/Applications/Tools $ ruby -W0 c50442.rb 3 323 312 231
#23
312
231

-W0ไม่จำเป็นต้องตั้งค่าสถานะแต่ฉันขอแนะนำให้คุณเพิ่มเพื่อปิดการใช้งานคำเตือนหรือเปลี่ยนเส้นทางstderr...

บอกฉันว่าคุณมีความอดทนพอที่จะใช้มันในตัวอย่างสำหรับ n = 6,7,8

การเปลี่ยนแปลง

  • eachmapขอบคุณ @NotThatCharles
  • ตรวจสอบการลบที่อยู่ติดกันและตัวเลขเดียวกันโดยสองregexps คล้ายกับสิ่งที่ @NotThatCharles แนะนำ
  • เพิ่มประสิทธิภาพการอ่านอินพุตเล็กน้อย
  • เล็กลง & ช้าลง

การปรับปรุงขนาดเพิ่มขึ้นเล็กน้อย: \dสั้นกว่า[^#]ในบรรทัดสุดท้าย; M.times.to_aนานกว่า(0..M-1).to_a
ไม่ใช่ว่า Charles

@ NotThatCharles ขอบคุณสำหรับคำแนะนำ! แต่สั้นกว่าM.times.to_a1 ไบต์;) ทำงานด้วยและมีความยาวเท่ากัน (0..M-1).to_a(0...M).to_a
blutorange

... การนับเป็นเรื่องยาก
ไม่ใช่ว่า Charles

จริงแล้วมันเสร็จสมบูรณ์เมื่อ n = 8?
ไม่ใช่ว่า Charles

@NotthatCharles หากคุณรอนานพอหรือใช้พีซีที่เร็วเป็นพิเศษ นี่คือรหัสกอล์ฟโดยไม่มีข้อ จำกัด ใด ๆ ที่เป็นความเร็วดังนั้นฉันจัดลำดับความสำคัญรหัสความยาว ...
blutorange

5

ทับทิม - 541 ... , 394

อัลกอริทึมพื้นฐานคือการค้นหาความลึกแรก recursive ซ้ำเพื่อยืนยันเลือกมองผ่านแถวที่ 1 แล้วคอลัมน์ 1 แล้วแถวที่ 2, ฯลฯ และการตรวจสอบว่าสองประเทศเพื่อนบ้านไม่ได้ถูกฆ่าตายและตารางมีการเชื่อมต่อ (ที่break ifประโยคหนึ่งใน ตรงนั้นและบิตที่มาก่อน)

K=(0...(N=gets.to_i)*N).to_a
J=gets(p).split*''
H=->m{K&[m+1,m-1,m+N,m-N]}
Q=->k{s=[k[j=0]]
(j=s.size
s.map{|x|(s+=H[x]&k).uniq!})while s[j]
break if(K-k).any?{|m|(H[m]-k)[0]}||k!=k&s
$><<K.map{|m|[k.index(m)?J[m]:?#,m%N>N-2?"
":p]}*''|exit if !g=((0...N*2).map{|x|(k.select{|m|m.divmod(N)[x/N]==x%N}.group_by{|m|J[m]}.find{|l,c|c[1]}||[])[1]}-[p]).min
g.map{|d|Q[k-g<<d]}}
Q[K]
puts"no answer"

เทคนิคบางอย่างเรียบร้อย:

if w[1]สั้นกว่าif !w.one?และถ้าคุณรู้ว่ามีสมาชิกอย่างน้อยหนึ่งคนก็เป็นผลลัพธ์เดียวกัน

ในทำนองเดียวกัน[0]จะสั้นกว่าany?หากไม่มีบล็อกและs[j]เป็นทางลัดที่น่ารักสำหรับj<s.size(ในทางเทคนิคแล้วจะมีลักษณะเหมือนj.abs<s.size)

และy%N+(y/N).iสั้นกว่ามากComplex(y%N,y/N)

นอกจากนี้เมื่อมีสองเงื่อนไขที่ซับซ้อนในการสร้างสตริงมันอาจจะสั้นกว่าที่จะทำ[cond1?str1a:str1b,cond2?str2a:str2b]*''มากกว่าการเพิ่ม parens หรือ#{}s ทั้งหมด

Ungolfing และคำอธิบาย:

(นี่คือจากรุ่น 531 byte ฉันได้ทำการเปลี่ยนแปลงที่สำคัญที่สุดตั้งแต่ฉันได้ยกเลิกการเรียกใช้ผลิตภัณฑ์ - เพียงแค่แก้หนึ่งหลักต่อแถว / คอลัมน์ในแต่ละครั้งและตอนนี้ J เป็นเพียงอาร์เรย์ที่จัดทำดัชนีโดย จำนวนเต็มพิกัดทั้งหมดเป็นเพียงจำนวนเต็ม)

H คำนวณเพื่อนบ้าน

def H m 
  # m, like all indices, is a complex number 
  #    where the real part is x and the imaginary is y
  # so neighbors are just +/-i and +/-1

  i='i'.to_c
  neighborhood = [m+1, m-1, m+i, m-i]

  # and let's just make sure to eliminate out-of-bounds cells
  K & neighborhood
end

N คือขนาดของกริด

N = gets.to_i

K คือกุญแจสู่แผนที่ (จำนวนเชิงซ้อน)

# pretty self-explanatory
# a range of, e.g., if N=3, (0..8)
# mapped to (0+0i),(1+0i),(2+0i),(0+1i),(1+1i),(2+1i),...
K = (0..N**2-1).map{|y| (y%N) +(y/N).i }

J คือแผนที่อินพุต (คุก)

# so J is [[0+0,"2"],[0+1i,"3"],....].to_h
J=K.zip($<.flat_map {|s|
  # take each input line, and...
  # remove the "\n" and then turn it into an array of chars 
  s.chomp.chars
}).to_h

k เป็นกุญแจที่ไม่ถูกฆ่า

# starts as K

Q เป็นวิธีการเรียกซ้ำหลัก

def Q k
  j=0 # j is the size of mass
  # the connected mass starts arbitrarily wherever k starts
  mass=[k[0]]
  while j < s.size # while s hasn't grown
    j = mass.size   
    mass.each{|cell|
      # add all neighbors that are in k
      (mass+=H[cell] & k).uniq!
    }
  end
  # if mass != k, it's not all orthogonally connected
  is_all_connected = k!=k&mass

  # (K-k) are the killed cells 
  two_neighbors_killed = (K-k).any?{|m|
    # if any neighbors of killed cells aren't in k,
    # it means it was killed, too 
    (H[m]-k)[0]
  }
  # fail fast
  return if two_neighbors_killed || is_all_connected

  def u x
    x.group_by{|m|J[m]}.select{|l,c|c[1]}
  end

  rows_with_dupes = Array.new(N){|r|u[k.select{|m|m.imag==r}]}

  cols_with_dupes = Array.new(N){|r|u[k.select{|m|m.real==r}]}

  # dupes is an array of hashes
  # each hash represents one row or column.  E.g.,
  #   {
  #     "3"=>[(0+0i),(1+0i),(3+0i)],
  #     "2"=>[(2+0i),(4+0i)]
  #   }
  # means that the 0th, 1st and 3rd cells in row 0
  # all are "3", and 2nd and 4th are "2".
  # Any digits without a duplicate are rejected.
  # Any row/col without any dupes is removed here.
  dupes = (rows_with_dupes+cols_with_dupes-[{}])

  # we solve one row at a time
  first_row = dupes[0]

  if !first_row
    # no dupes => success!
    J.map{|m,v|k.member?(m)?v:?#}.each_slice(N){|s|puts s*''}
    exit
  else
    # the digit doesn't really matter
    t=first_row.values

    # cross-multiply all arrays in the row to get a
    # small search space. We choose one cell from each
    # digit grouping and drop the rest.
    t.inject(:product).map{ |*e|
      # Technically, we drop all cells, and add back the
      # chosen cells, but it's all the same.
      new_k = k-t.flatten+e.flatten

      # and then search that space, recursively
      Q[new_k]
    }
  end
end

รหัสจะถูกดำเนินการด้วย:

# run with whole board
Q[K]

# if we get here, we didn't hit an exit, so we fail
puts"no answer"

การเปลี่ยนแปลง

เพิ่ม394คำแนะนำของ @ blutorange ด้านล่างและตัดการจัดการที่มากขึ้น

408แก้ไขผลลัพธ์อีกครั้ง ใช้.minแทน.inject(:+)เพราะฉันเอาแค่แถวเดียวอยู่ดี

การคำนวณผลลัพธ์ที่สั้นลง417

421ลดจำนวนเชิงซ้อน เพียงใช้จำนวนเต็ม บันทึกบันเดิล

ปรับปรุงอินพุตเพิ่มอีก450 รายการ

การปรับปรุงอินพุต456

การปรับปรุงที่เพิ่มขึ้น462 - esp findไม่ใช่select

475ดร็อปuและบีบตัวสร้างแถว / คอลัมน์คู่

503แก้ไขตัวเลขที่ซ้ำกันหนึ่งหลักต่อแถว / คอลัมน์ในแต่ละครั้ง

530ใช้map &:popแทนvalues

531ดึงแลมบ์ดาออกมาซึ่งทำให้อาเรย์ของคู่หู

552โอ๊ะโอ! พลาดความต้องการ

536 การปรับปรุงจำนวนประชากรของอาร์เรย์ที่ซ้ำกัน (ก่อนหน้านี้คืออะไรd)

เริ่มต้น541


ภายใน lambdas breakสามารถใช้แทนreturnอาจบันทึกได้อีกหนึ่งไบต์ ฉันชอบไลค์นี้จริง ๆ กลอุบายมากมายและเร็วกว่ามาก
blutorange

@ blutorange ขอบคุณ! ประยุกต์ ยังมีวิธีที่จะไปกด 344 ได้
ไม่ใช่ว่า Charles

อีกหน่อยใช่ แต่อย่างอื่นมันดูดี อีกอย่างที่ฉันเห็น: ในบรรทัดที่สองเนื่องจากตัวแปรaถูกใช้เพียงครั้งเดียวคุณสามารถทำสิ่งนั้นJ=gets(p).split*''ได้ คุณได้ลองโต้แย้งข้อโต้แย้งดูคำตอบของฉัน?
blutorange

3

HTML + JavaScript ( ES6 ) 459

การใช้ textarea HTML เพื่อรับอินพุตหลายบรรทัด

ในการทดสอบให้รันตัวอย่างใน Firefox ขยาย textarea หากคุณต้องการวางการป้อนข้อมูลใน textarea (ระวัง: การป้อนข้อมูลที่แน่นอนไม่มีช่องว่างพิเศษในบรรทัดใด ๆ ) และแท็บออกไป ผลลัพธ์จะถูกต่อท้าย

วิธีการ: Serarch First Depth แบบซ้ำ พบวิธีแก้ปัญหาที่ไม่เหมาะสมสำหรับกรณีทดสอบทั้งหมดในไม่กี่วินาที (เป็น gode golf แต่คำตอบที่ถูกต้องควรยุติสำหรับกรณีทดสอบทั่วไป)

<textarea onchange="s=this.value,
  z=s[0],o=-~z,k=[],X='no answer',f='#',
  (R=(s,t,h={},r=[],d=0)=>(
    s.map((v,i)=>v>0&&[i%o,~(i/o)].map(p=>h[p+=v]=[...h[p]||[],i])),
    [h[i][1]&&h[i].map(p=>r[d=p]=p)for(i in h)],
    d?r.some(p=>(
      (s[p+o]!=f&s[p-o]!=f&s[p-1]!=f&s[p+1]!=f)&&
      (
        g=[...s],g[p]=f,e=[...g],n=0,
        (F=p=>e[p]>0&&[1,-1,o,-o].map(d=>F(p+d),e[p]=--n))(p<o?p+o:p-o),
        t+n==0&&!k[g]&&(k[g]=1,R(g,t-1))
      )
    )):X=s.join('')
  ))([...s.slice(2)],z*z-1),this.value+=`

`+X"></textarea>

ครั้งแรกลอง

วิธีการ: Deparch First Serarch ไม่ใช่แบบเรียกซ้ำโดยใช้สแต็กผู้ใช้
ฟังก์ชั่นนี้สามารถเปลี่ยนได้อย่างง่ายดายในการค้นหาครั้งแรกของ Breadth l.popเพื่อเปลี่ยนl.shiftให้ใช้คิวแทนสแต็ก แต่มันช้าเกินไปและฉันไม่แน่ใจว่าจะสามารถหาทางออกที่ดีที่สุดได้หรือไม่

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