Blok Penataan Ulang


14

Jadi tugas Anda adalah mengambil blok 3x3 di mana -berarti ruang kosong, dan *berarti ruang penuh, misalnya:

-**
-*-
*-*

dan mengatur ulang blok sehingga *membentuk X, seperti ini:

*-*
-*-
*-*

Input: kotak 3x3 seperti di atas, bisa berupa 3 baris, array, atau apa pun yang Anda inginkan.

Keluaran: Jumlah gerakan tersingkat untuk disusun ulang menjadi X. Setiap gerakan membalik 2 karakter yang saling bersentuhan, dan saling horizontal, saling vertikal, atau diagonal satu sama lain. Jika tidak memungkinkan, kembalikan output yang tidak mungkin, misalnya 999atau -4242. 5adalah nomor terkecil seperti itu.

Kasus uji:

1) Output: 1

-**
-*-
*-*

2) Output: -1

-*-
-*-
*-*

3) Output: 3

---
-**
***

4) Output: 0

*-*
-*-
*-*

Anda dapat mengganti karakter kosong dan non kosong tetapi pastikan untuk memasukkan yang mana dalam posting Anda

Golf kode

Ingat ini adalah kode golf kode yang paling pendek menang!


1
Dengan membalik 2 karakter, apakah maksud Anda beralih dari angkasa ke *dan sebaliknya, atau menukar mereka?
user202729

Bagaimana jika ada lebih dari lima *? Bisakah Anda menambahkan beberapa test case lagi?
Stewie Griffin

@ user202729 misalnya abc akan menjadi acb jika Anda membalik 2 karakter terakhir.
Noah Cristino

@StewieGriffin "jika tidak memungkinkan mengembalikan -1" lebih dari 5 *atau kurang dari 5 membuatnya tidak mungkin.
Noah Cristino

6
Bisakah kita menggunakan sesuatu selain -1? Misalnya 5(tidak mungkin sebaliknya), atau melempar kesalahan?
Jonathan Allan

Jawaban:


12

Python 3 , 104 78 byte

lambda n:-(sum(n)!=5)or sum(n[1::2])+n[4]*(max(n,n[6:],n[::3],n[2::3])>=[1]*3)

Cobalah online!

Sunting: Terapkan saran @Jonathan Allan's dan @ xnor untuk secara drastis mengurangi jumlah byte.

Input adalah daftar string dengan panjang 9 dengan nol dan satu, yang menjadi *s.

Berikut beberapa pengamatan:

  • Kita tidak perlu memindahkan bintang-bintang di sel yang benar. Setiap bintang yang salah tempat memiliki 5 sel di sekitarnya yang tidak dapat diblokir sekaligus (jika tidak jawabannya adalah -1).
  • Biaya untuk setiap bintang yang salah tempat adalah 1 atau 2, dan itu hanya 2 jika dikelilingi oleh tiga bintang yang ditempatkan dengan benar.
  • Biaya untuk setiap bintang yang salah tempat tidak tergantung satu sama lain.

Oleh karena itu, pertama-tama kami menguji apakah string memiliki lima, dan kemudian menghitung hal-hal ini:

  • Jumlah bintang yang salah tempat (= yang memiliki indeks ganjil)
  • Jumlah bintang salah tempat biaya 2 (= sel di 0124, 0346, 2458, 4678karena semua orang)
    • Faktor keluar n[4]menjadi satu, lalu uji setiap ekstraksi rentang '111'.
    • Karena bintang tersebut adalah paling banyak satu, kita dapat menggunakan maxbukan sum.

Simpan 17 byte dengan menerima daftar alih-alih string (mengganti counts dengan sums dan '111'dengan [1]*3) TIO (Saya sudah mencoba menjadi pintar dengan n[i::j]>=[1]*3loop tetapi belum menemukan yang lebih pendek).
Jonathan Allan

Karena hanya ada satu bintang berbiaya-2, sepertinya Anda bisa melakukannya max(n,n[6:],n[::3],n[2::3])>='1'*3.
xnor

Ada pengaturan lain yang memiliki bintang biaya-2. Saya pikir [0,1,1,1,1,0,1,0,0] harus mengembalikan 3 bukannya 2.
RootTwo

Juga, [1,1,1,1,0,0,1,0,0]] seharusnya 3 bukannya 2.
RootTwo

Juga, [1,1,1,1,0,0,1,0,0]] seharusnya 3 bukannya 2.
RootTwo

4

Jelly , 26 byte

5ḶḤd3ạŒ!Ṁ€€ḅ1Ṃ
T’d3Ç-L=5Ɗ?

Cobalah online!


Ambil daftar datar sebagai masukan.

Sayang sekali bahwa Jelly tidak memiliki "indeks kebenaran multidimensi" ... T€ṭ€"JẎjuga berfungsi tetapi membutuhkan 1 byte lebih.


Algoritma: Ada 5 posisi blok saat ini dan 5 target (tujuan), algoritma mencoba masing-masing dari 5! cocok, dan output jumlah minimum jarak [sumber, tujuan] Chebyshev.


Anda dapat mengambil daftar datar ("apa pun yang Anda inginkan") ... mungkin Anda bahkan dapat mengambil indeks berbasis 0 dan memiliki 24?
Jonathan Allan

4

Haskell , 176 132 126 104 byte

w=0:1:w
m a|sum a/=5=5|1>0=sum$[a!!4|3<-sum.map(a!!)<$>[[0,1,2],[0,3,6],[2,5,8],[6,7,8]]]++zipWith(*)a w

Cobalah online!


Mengambil daftar bilangan bulat dengan 1 sebagai karakter non-kosong. Jumlahkan jumlah kuadrat tidak nol yang diindeks, kemudian tambahkan 1 jika ada pola gerakan ganda ditemukan (kolom tengah dan kolom tepi / baris terisi penuh). Bagian terakhir agak boros menurut saya, mungkin bisa lebih ditingkatkan dari metode brute-force ini. Mengembalikan 5 (output yang tidak mungkin) pada input yang tidak mungkin.


2
Beberapa tips: lengthtes dapat disingkat menjadi sum[1|1<-a]. Berfungsi ske: (1-e,n+sum[1|b>e])yang dapat Anda sebaris untuk menyimpan byte lain. Anda dapat menggunakan otherwisepenjaga di muntuk menyimpan sepasang (). Akhirnya, &&di tingkat atas di penjaga dapat digantikan oleh ,. ...
nimi

2
Anda dapat menyimpan byte lain dengan menggunakan sumpemahaman daftar untuk melemparkan Boolean ke int. Cobalah online!
Posting Rock Garf Hunter

2
Sebenarnya Anda dapat menyimpan beberapa byte karena begitu penjaga pola hilang Anda bisa memindahkan semuanya ke dalam m. Cobalah online!
Post Rock Garf Hunter

2
Juga karena setiap elemen non-1 aharus tidak 0dapat Anda gunakan, sum abukan sum[1|1<-a]? Cobalah online!
Post Rock Garf Hunter

1
Aku baru sadar karena tidak bisa ada lebih dari 1 sisi dengan semua 1s kecuali pusat adalah 0, Anda dapat melakukan 3<-bukan elem 3$. Anda juga dapat menggunakan sum.map(a!!)bukan sum<$>map(a!!).
Posting Rock Garf Hunter

3

Python 2 , 194 192 byte

from itertools import*
f=lambda l,k=0:-(sum(l)!=5)or[1,0]*4!=l[:-1]and k<4and-~min(f(l[:a]+[l[b]]+l[a+1:b]+[l[a]]+l[b+1:],k+1)for a,b in combinations(range(9),2)if max(b/3-a/3,abs(a%3-b%3))<2)

Cobalah online!


1
Tidak bekerja dengan [0,1,0,1,0,1,1,1,0](diharapkan: 4, aktual: 13).
Bubbler

@Ubbler memperbaikinya
ovs

3

JavaScript (ES6), 123 byte

Mengambil input sebagai bilangan bulat 9-bit. Memecahkan teka-teki dengan menerapkan aturan secara naif, yang telah terbukti tidak menjadi pendekatan terpendek.

f=(n,k=b=-1)=>n^341?k>2?b:[3,6,9,10,17,18,20,34,36].map(m=>[1,8,8].map(M=>(x=n&(m*=M))&-x^x||f(n^m,k+1)))|b:!~b|k<b?b=k+1:b

Cobalah online!

Berkomentar

f = (                           // f = recursive function taking:
  n,                            //   n = input
  k =                           //   k = number of moves, initialized to -1
  b = -1                        //   b = best result so far, initialized to -1
) =>                            //
  n ^ 341 ?                     // if n does not match the target pattern:
    k > 2 ?                     //   if we've already done more than 3 moves:
      b                         //     we're not going to find a solution -> abort
    :                           //   else:
      [3,6,9,10,17,18,20,34,36] //     for each swap bitmask m
      .map(m =>                 //     and
      [1,8,8]                   //     for each multiplier M:
      .map(M =>                 //       apply the multiplier to m and
        (x = n & (m *= M))      //       apply the final bitmask to n -> this gives x
        & -x                    //       isolate the least significant bit of x
        ^ x ||                  //       if it's the only bit set,
        f(n ^ m, k + 1)         //       then swap the bits and make a recursive call
      )) | b                    //     end of both map() loops; return b
  :                             // else:
    !~b | k < b ? b = k + 1 : b //   this is a solution in k+1 moves: update b

NB : Kode ini melakukan beberapa gerakan ilegal di luar bagian atas papan ketika m dikalikan dengan 64. Tetapi mereka diabaikan, karena mereka tidak mungkin mengarah pada solusi yang lebih pendek daripada solusi hukum terbaik.

Di bawah ini adalah 9 bit swap dasar dan pola target. Pojok kiri atas adalah bit yang paling signifikan.

000  000  001  001  010  010  010  100  100     101
011  110  001  010  001  010  100  010  100     010 (341)
(3)  (6)  (9)  (10) (17) (18) (20) (34) (36)    101

Bisakah Anda menautkan hexdump untuk pengujian? Juga, saya tidak tahu bilangan bulat 9 bit dimungkinkan di JS
Stan Strum

@StanStrum Diperbarui ke versi yang lebih pendek dengan penyandian yang lebih mudah. (Dan ya: JS mendukung operasi bitwise hingga 32 bit.)
Arnauld

2

Jelly , 26 byte

“ċȤ‘ḤB;U$=a¥;Ḋm2ƊẠ€SɓSn5Nȯ

Cobalah online!

Tautan monadik.

Bagaimana?

Terinspirasi oleh jawaban Python Bubbler ; golf sesuai dengan Jelly ...

“ċȤ‘ḤB;U$=a¥;Ḋm2ƊẠ€SɓSn5Nȯ - Link: length 9 list of ones & zeros, X
“ċȤ‘                       - list of code-page indices     = [232,154]
    Ḥ                      - double                        = [464,308]
     B                     - to binary     = [[1,1,1,0,1,0,0,0,0],[1,0,0,1,1,0,1,0,0]]
        $                  - last two links as a monad:
       U                   -   upend       = [[0,0,0,0,1,0,1,1,1],[0,0,1,0,1,1,0,0,1]]
      ;                    -   concatenate = [[1,1,1,0,1,0,0,0,0],[1,0,0,1,1,0,1,0,0],[0,0,0,0,1,0,1,1,1],[0,0,1,0,1,1,0,0,1]]
           ¥               - last two links as a dyad:
          a                -   logical AND (vectorises)
         =                 -   equal? (vectorises)
                Ɗ          - last three links as a monad:
             Ḋ             -   dequeue X (remove leftmost element)
               2           -   literal two
              m            -   modulo slice (keeps the "edge-elements") 
            ;              - concatenate
                 Ạ€        - all? for €ach (edge-elements: no-op
                           -                else: 1 for any cost-2 element 0 otherwise)
                   S       - sum
                    ɓ      - new dyadic chain ^that on the right; X on the left
                     S     - sum X
                       5   - literal five
                      n    - not equal?
                        N  - negate (-1 if not exactly 5 1s, 0 otherwise)
                         ȯ - logical OR with right

2

JavaScript, 85 byte

s=>/^0*(10*){5}$/.test(s)*s.match(/(?=1.(..)*$|^1(..)?11.1|1.11(..)?1$)|$/g).length-1

Ini adalah port regex dari jawaban Bubbler .

Input sebagai string 0/1.


2

Stax , 23 22 byte

Ç╙╤Ü┤└åVτ┐├Y-²▼░█∩¡3ëâ

Jalankan dan debug itu

Program ini membutuhkan array [0, 1] sebagai input, dan mengembalikan jumlah gerakan integer, atau string kosong jika tidak ada solusi yang mungkin.

Pertimbangkan indeks ini untuk kisi

0 1 2
3 4 5
6 7 8
  • Jika tidak ada tepatnya 5 1 input , maka tidak ada solusi, jadi kami tidak menghasilkan output.
  • Pusat dari setiap sisi adalah posisi yang salah. Ini adalah indeks 1, 3, 5, dan 7. Menjumlahkan jarak untuk masing-masing1 di posisi ini akan menghasilkan hasil akhir.
  • Untuk masing-masing 1dalam posisi yang salah jaraknya adalah 1 atau 2. Ini akan menjadi 2 jika itu dikelilingi oleh yang lain 1. Misalnya, jika ada 1s pada indeks [0, 1, 2, 4], maka jarak untuk yang salah 1adalah 2.
  • Dengan mengingat hal ini, pertimbangkan kode semu ini untuk mendapatkan jarak yang berkontribusi pada hasil dengan indeks 1.

    1. Baca 4 bit dari indeks [1, 0, 2, 4]. Ini menempatkan posisi yang salah di posisi yang paling signifikan.
    2. Ubah bit-bit ini menjadi angka b dari 0 menjadi 15.
    3. Kapan 0 <= b <= 7jaraknya 0. Saat8 <= b <= 14 jaraknya adalah 1. Ketika b == 15jaraknya 2. Ini bisa dihitung menggunakan pembagian integer oleh b * 2 / 15.

Jadi total jarak dapat dihitung dengan mengulangi proses ini 4 kali dan memutar grid di antaranya.

1#5=4*  if the number of 1s is 5, then 4, else 0
D       repeat the rest of the program that many times
  x     push the value in the x register, which is initially the input
  3/    split into 3 rows
  rM    rotate 90 degrees
  $X    flatten back into single array, and save the "rotated" array in the X register
  A|2E  get the digits of 2^10 i.e. [1,0,2,4]
  @     read the bits from the current rotation at indices [1,0,2,4]
  :b    convert bits to integer
  H15/  double, then divide by 2
  +     add to running total

Jalankan yang ini


Periksa hasil edit, setiap nilai yang mustahil diterima, bukan hanya -1 jika itu membantu Anda
Noah Cristino

Iya. Itu menghemat 2 byte.
rekursif

1

Excel, 86 81 Bytes

=SUM(B1,A2,B3,C2)+B2*(AND(A1:A3)+AND(A1:C1)+AND(C1:C3)+AND(A3:C3))/(SUM(A1:C3)=5)

Lama: Ketika output 'tidak mungkin' adalah-1

=IF(SUM(A1:C3)=5,SUM(B1,A2,B3,C2)+B2*(AND(A1:A3)+AND(A1:C1)+AND(C1:C3)+AND(A3:C3)),-1)

Penggunaan 1untuk diisi dan 0kosong, input dalam jangkauan A1:C3. Dimungkinkan untuk bermain golf lebih jauh jika kita dapat mengembalikan nilai selain -1karena "tidak mungkin". Mengembalikan #DIV/0!kesalahan pada grid yang tidak mungkin

Beroperasi pada logika yang sama dengan Bubbler's Python answer .


Periksa hasil edit, setiap nilai yang mustahil diterima, bukan hanya -1
Noah Cristino
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.