Seçici olarak pozitif tamsayıları öldürmek


21

Giriş

Aritmetik Gaol, pozitif tamsayıları hapseden özel bir tesistir. Ancak son zamanlarda pozitif tamsayılar kaçmaya çalışıyor. Bu nedenle, gardiyanlar , diğer tam sayılara bir mesaj göndermek için bazı pozitif tam sayıların kaldırılmasına karar vermiştir . Maksimum etki için hangi tam sayıların giderileceğini bulmak için bir program yazmak için bir yazılım mühendisi kiraladılar.

Giriş açıklaması

Giriş, STDIN, komut satırı argümanları veya bir kullanıcı giriş fonksiyonu (örneğin raw_input) aracılığıyla verilir. Bir fonksiyon argümanı veya önceden başlatılmış bir değişken olarak sahip olamazsınız (örneğin, bu program bir değişkene girdi bekliyor x).

Giriş ilk çizgi bir tek pozitif tamsayı içerir nburada 8 >= n >= 3. Bunun ardından kümedeki karakterleri niçeren satırlar bulunur . İşte bir örnek giriş:n[1,2,3,4,5,6,7,8,9]

5
22332
46351
65455
24463
65652

Çıkış açıklaması

Gardiyanlar sayıları ortadan kaldırmak istiyor ve aşağıdaki şartların yerine getirilmesi gerekiyor:

  • Sonuçta ortaya çıkan kılavuzun her satırında ve sütununda, iki kez hiçbir sayı görünmez;
  • Yok edilen iki sayı yatay veya dikey olarak bitişik olamaz;
  • Hayatta kalan sayılar ortogonal olarak bitişik bir grup oluşturmalıdır - hayatta kalan herhangi bir sayıdan yalnızca yatay ve dikey hareket eden ve hiçbir zaman ortadan kaldırılmış herhangi bir sayıyı geçmeden kalan herhangi bir sayıya seyahat etmek mümkün olacaktır.

Girdiyi (eksi ilk satır eksi), çıkarılan sayılar ile değiştirilerek çıkartın #.

Birden fazla çözüm olabilir. Bu durumda, herhangi bir çözümü üretebilirsiniz.

Ayrıca bir çözüm olmayabilir. Bu durumda, dizgeyi çıktılayın no answer.

Örnek giriş için olası bir çıktı:

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

Örnek Girişler ve Çıkışlar

Her giriş için birden fazla çıkış vardır, bu yüzden bu çıkışlar sadece örneklerdir.

Giriş:

5
46551
51565
32654
14423
43244

Çıktı:

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

Giriş:

7
7183625
1681563
5238564
8786268
1545382
3814756
5325345

Çıktı:

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

Giriş:

8
21534768
75196287
68392184
96244853
44865912
76516647
89751326
43698979

Çıktı:

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

Giriş:

4
2222
2331
3112
1322

Çıktı:

no answer

4
( Singles olarak da bilinir .)
Doorknob

Bu yapboz mükemmel. Teşekkür ederim. Bir çözüm üzerinde çalışma
Charles Değil

1
Bu bulmacayı sevdim, ancak tek kullanıcı giriş yöntemi promptçoklu satır girişine izin vermediğinden , tarayıcıda JavaScript kullanarak "olduğu gibi" yanıtlanamıyor .
edc65

Yanıtlar:


0

Ruby, 346 344 329 316 bayt, sl∞∞∞∞∞∞w

Bu kod golf, kod hızlı değil, o yüzden ...

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"

Gibi kullanın:

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

Bayrak -W0gerekli değildir, ancak uyarıları devre dışı bırakmak için eklemenizi ya da yönlendirmenizi öneririm stderr...

Bana n = 6,7,8 örneklerinde çalıştırmak için yeterli sabrınız olup olmadığını söyleyin

Değişiklikler

  • eachmap, @NotThatCharles sayesinde
  • regexp@NotThatCharles'ın önerdiğine benzer şekilde bitişik silmeleri ve aynı haneleri iki saniye boyunca kontrol edin
  • optimize edilmiş okuma girişi biraz
  • daha küçük ve daha yavaş

boyutta birkaç artan iyileştirme: sondan iki sıradaki çizgiden \ddaha kısadır [^#]; M.times.to_adaha uzun(0..M-1).to_a
Charles

@NotThatCharles İpuçları için teşekkürler! Ama M.times.to_a1 bayt olan kısa daha (0..M-1).to_a); (0...M).to_açok çalışıp çalışmadığını ve aynı uzunlukta.
blutorange

... saymak zordur
Charles

n = 8 olduğunda gerçekten tamamlandı mı?
Charles,

@NotthatCharles Yeterince looo beklerseniz veya süper hızlı bir bilgisayar kullanıyorsanız, evet. Bu, hız konusunda herhangi bir kısıtlama olmaksızın bir kod
golfüdür

5

Ruby - 541, 394

Temel algoritma, yinelemeli olarak seçilecek, satır 1'e, sonra sütun 1'e, sonra satır 2'ye vb. Bakarak ve iki komşunun öldürülmediğini ve şebekenin bağlı olduğunu kontrol eden, yinelemeli bir derinlikli ilk break ifaramadır. orada ve ondan önce gelen bit).

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"

Bazı temiz hileler:

if w[1]çok daha kısa if !w.one?ve en az bir üye olduğunu biliyorsanız, aynı sonuç.

Benzer şekilde, blok olmadığından [0]daha kısa any?ves[j] şirin bir kısayol j<s.size(teknik olarak daha çok gibi j.abs<s.size)

Ve y%N+(y/N).i çok daha kısaComplex(y%N,y/N)

Ayrıca, dizeleri oluşturmak için iki karmaşık koşul olduğunda, yapılması daha kısa olabilir [cond1?str1a:str1b,cond2?str2a:str2b]*'' tüm parenleri eklemek#{} .

Ungolfing ve açıklama:

(Bu 531 bayt sürümündedir. Değişiklikler yaptım. En önemlisi, ürüne yapılan çağrıyı iptal ettim - bir seferde satır / sütun başına sadece bir rakamı çözüyorum ve J şimdi sıralı bir dizi. tamsayılar.Tüm koordinatlar sadece tamsayılardır.

H komşuları hesaplar

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 ızgara boyutu

N = gets.to_i

K haritanın anahtarları (karmaşık sayılar)

# 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 giriş haritası (hapishane)

# 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 öldürülmemiş anahtarlar

# starts as K

Q ana özyinelemeli yöntem

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

Kod şu şekilde yürütülür:

# run with whole board
Q[K]

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

Değişiklikler

394 , @ blutorange'nin önerisini aşağıya ekledi ve çok daha fazla manipülasyon ortaya çıkardı

408, çıktıyı bir kez daha revize etti. Ayrıca .minyerine kullanın.inject(:+) zaten sadece bir satır alıyorum çünkü .

417 kısa çıktı hesabı

421 karmaşık sayıları düşürdü. Sadece tamsayıları kullanın. Bir paket kaydet

450 giriş girişi daha

456 giriş geliştirmeleri

462 artan iyileştirmeler - esp. find, değilselect

475 düştüu ve sıra / sütun dupe oluşturucusunu ezdi

503 , her seferinde satır / sütun başına yalnızca bir yinelenen rakamı çözer.

530 kullanım map &:popyerinevalues

531 dupes dizisini oluşturan lambdaları çıkarır

552 ayy! bir gereksinimi kaçırdım

536 marjinal olarak gelişmiş dupes dizisi popülasyonu (önceden olanlar d)

541 ilk


İç mekan lambdaları breakyerine kullanılabilir return, bir bayttan daha tasarruf edebilir. Bunu gerçekten çok seviyorum, çok fazla hile ve çok daha hızlı.
blutorange

@blutorange Teşekkürler! Uygulamalı. Yine de 344'ü vurmanın bir yolu var.
Charles,

Biraz daha uzun, evet, ama aksi halde iyi görünüyor. Gördüğüm bir şey daha: İkinci satırda, değişken ayalnızca bir kez kullanıldığı için bunu başarabilirsiniz J=gets(p).split*''. Cli tartışmalarını denediniz mi, cevabımı gördünüz mü?
blutorange

3

HTML + JavaScript ( ES6 ) 459

Çok satırlı giriş elde etmek için bir HTML textarea kullanma.

Test etmek için, snippet'i Firefox'ta çalıştırın. İsterseniz textarea'yı büyütün, girdiyi textarea'nın içine yapıştırın (dikkatli olun: kesin girdi, herhangi bir satırda fazladan boşluk yok) ve sekmeyi kaldırın. Sonuç eklenmiştir.

Yöntem: özyinelemeli Derinlik İlk Serarch. Saniyeler içinde tüm test durumları için optimal olmayan çözümler bulur (gode golf, ancak geçerli bir test durumu için geçerli bir cevap kesilmelidir )

<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>

İlk deneme

Yöntem: Derinlik İlk Serarch, özyinelemesiz, bir kullanıcı yığını kullanarak.
Fonksiyon kolayca chaging, bir Genişlik Birinci Ara dönüştürülmüş olabilir l.popiçin l.shiftöylesine bir kuyruk yerine bir yığın kullanarak, ama çok yavaş ve emin o yine de bir optimum çözüm bulabilirsiniz değilim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.