Tantangan Golf Es

24

Tujuan dari tantangan ini adalah untuk menulis program atau fungsi yang mengembalikan jumlah serangan paling sedikit yang diperlukan untuk menyelesaikan kursus yang diberikan.

Memasukkan

  • Tata letak kursus dapat diteruskan dengan cara dan format yang sesuai yang Anda inginkan. (baca dari konsol, diteruskan sebagai parameter input, baca dari file atau lainnya, multiline-string, array string, karakter dua dimensi / array byte).
  • Posisi awal bola dan lubang bisa dilewati sebagai input juga, itu tidak harus diurai dari input. Dalam kasus uji mereka dimasukkan dalam kursus untuk memastikan tidak ada kebingungan tentang posisi sebenarnya.
  • Anda dapat memetakan kembali karakter input ke sesuatu yang lain, selama mereka masih dapat dikenali sebagai karakter yang berbeda (mis. Karakter ASCII yang dapat dicetak).

Keluaran

  • Program harus mengembalikan skor serendah mungkin (jumlah paling sedikit serangan yang diperlukan untuk mencapai lubang) untuk setiap kursus lulus sebagai input dalam format yang masuk akal (string, integer, float atau haiku yang menggambarkan hasil)
  • Jika kursus tidak mungkin dikalahkan, kembalikan -1(atau nilai kepalsuan lain pilihan Anda yang tidak akan dikembalikan untuk kursus yang dapat dikalahkan ).

Contoh:

Dalam contoh ini posisi diberi notasi berbasis 0, X / Y, kiri-ke-kanan, atas-bawah - tetapi Anda dapat menggunakan format apa pun yang Anda suka karena hasilnya benar-benar bebas format.

Memasukkan:

###########
#     ....# 
#      ...# 
#  ~    . # 
# ~~~   . # 
# ~~~~    # 
# ~~~~    # 
# ~~~~  o # 
# ~~~~    # 
#@~~~~    # 
###########

Ball (Start-Position): 1/9
Hole (End-Position):   8/7

Keluaran:

8

Contoh saja

Aturan dan bidang

Kursus ini dapat terdiri dari bidang-bidang berikut:

  • '@' Ball - Awal kursus
  • 'o' Hole - Tujuan dari kursus
  • '#' Wall - Ball akan berhenti ketika membentur dinding
  • '~' Air - Harus dihindari
  • '.' Pasir - Bola akan segera berhenti di pasir
  • ' ' Ice - Ball akan terus meluncur sampai menyentuh sesuatu

Aturan dasar dan batasan permainan:

  • Bola tidak bisa bergerak secara diagonal, hanya kiri, kanan, atas dan bawah.
  • Bola tidak akan berhenti di depan air, hanya di depan dinding, di atas pasir dan di dalam lubang.
    • Tembakan ke dalam air tidak valid / tidak mungkin
    • Bola akan tetap berada di dalam lubang, tidak melewatinya seperti di es
  • Kursus selalu persegi panjang.
  • Kursus ini selalu dibatasi oleh air atau dinding (tidak diperlukan pemeriksaan batas).
  • Selalu ada tepat satu bola dan satu lubang.
  • Tidak semua kursus mungkin untuk dikalahkan.
  • Mungkin ada beberapa jalur yang menghasilkan skor (terendah) yang sama.

Celah dan Kondisi Kemenangan

  • Celah standar dilarang
  • Program harus diakhiri
  • Anda tidak dapat membuat aturan tambahan (memukul bola begitu keras hingga melompati air, melambung dari dinding, melompati ladang pasir, kurva di sudut, dll.)
  • Ini adalah , jadi solusi dengan jumlah karakter paling sedikit menang.
  • Solusi harus dapat menangani semua kasus uji yang disediakan, jika ini tidak mungkin karena pembatasan bahasa yang digunakan, harap sebutkan dalam jawaban Anda.

Uji kasus

Kursus # 1 (2 serangan)

####
# @#
#o~#
####

Kursus # 2 (tidak mungkin)

#####
#@  #
# o #
#   #
#####

Kursus # 3 (3 pukulan)

~~~
~@~
~.~
~ ~
~ ~
~ ~
~ ~
~.~
~o~
~~~

Kursus # 4 (2 serangan)

#########
#~~~~~~~#
#~~~@~~~#
##  .  ##
#~ ~ ~ ~#
#~. o .~#
#~~~ ~~~#
#~~~~~~~#
#########

Kursus # 5 (tidak mungkin)

~~~~~~~
~...  ~
~.@.~.~
~...  ~
~ ~ ~.~
~ . .o~
~~~~~~~

Lebih banyak kasus uji:

https://pastebin.com/Azdyym00

Manfred Radlwimmer
sumber
1
Terkait: Satu , Dua .
AdmBorkBork
Jika kita menggunakan array byte dua dimensi sebagai input, apakah kita diizinkan menggunakan pemetaan khusus untuk simbol?
Arnauld
@Arnauld Tidak yakin apa konsensus yang biasa tentang hal itu ada di sini, tapi saya akan mengatakan itu tidak apa-apa selama input masih dapat dikenali. Saya telah memperbarui bagian Input .
Manfred Radlwimmer
Jika memasukkan tujuan secara langsung, dapatkah kita meminta tempat tujuan menjadi simbol 'pasir'?
14m2
@ l4m2 Tentu, dengan cara itu akan tetap konsisten dengan semua aturan lainnya.
Manfred Radlwimmer

Jawaban:

6

JavaScript (ES6), 174 byte

Mengambil input dalam sintaks curling currying ([x, y])(a), di mana x dan y adalah koordinat 0-diindeks dari posisi awal dan [] adalah matriks bilangan bulat, dengan 0= es, 1= dinding, 2= pasir, 3= lubang dan4 = air

Kembali 0jika tidak ada solusi.

p=>a=>(r=F=([x,y],n,R=a[y],c=R[x])=>R[c&(R[x]=4)|n>=r||[-1,0,1,2].map(d=>(g=_=>(k=a[v=Y,Y+=d%2][h=X,X+=~-d%2])||g())(X=x,Y=y)>3?0:k>2?r=-~n:F(k>1?[X,Y]:[h,v],-~n)),x]=c)(p)|r

Cobalah online!

Berkomentar

p => a => (                       // given the starting position p[] and the matrix a[]
  r =                             // r = best result, initialized to a non-numeric value
  F = (                           // F = recursive function taking:
    [x, y],                       //   (x, y) = current position
    n,                            //   n = number of shots, initially undefined
    R = a[y],                     //   R = current row in the matrix
    c = R[x]                      //   c = value of the current cell
  ) =>                            //
    R[                            // this will update R[x] once the inner code is executed
      c & (R[x] = 4) |            //   set the current cell to 4 (water); abort if it was
      n >= r ||                   //   already set to 4 or n is greater than or equal to r
      [-1, 0, 1, 2].map(d =>      //   otherwise, for each direction d:
        (g = _ => (               //     g = recursive function performing the shot by
          k = a[                  //         saving a backup (h, v) of (X, Y)
            v = Y, Y += d % 2][   //         and updating (X, Y) until we reach a cell
            h = X, X += ~-d % 2]) //         whose value k is not 0 (ice)
          || g()                  //   
        )(X = x, Y = y)           //     initial call to g() with (X, Y) = (x, y)
        > 3 ?                     //     if k = 4 (water -> fail):
          0                       //       abort immediately
        :                         //     else:
          k > 2 ?                 //       if k = 3 (hole -> success):
            r = -~n               //         set r to n + 1
          :                       //       else:
            F(                    //         do a recursive call to F():
              k > 1 ?             //           if k = 2 (sand):
                [X, Y]            //             start the next shots from the last cell
              :                   //           else (wall):
                [h, v],           //             start from the last ice cell
              -~n                 //           increment the number of shots
            )                     //         end of recursive call
      ), x                        //   end of map(); x = actual index used to access R[]
    ] = c                         // restore the value of the current cell to c
)(p) | r                          // initial call to F() at the starting position; return r
Arnauld
sumber
5

Python 3 , 273 byte

def p(g,c,d,k=0):
	while 1>k:c+=d;k=g.get(c,9)
	return-(k==2)or c-d*(k==3)
def f(g):
	c={q for q in g if g.get(q,9)>4};I=0;s=[c]
	while all(g.get(q,9)-4for q in c):
		c={k for k in{p(g,k,1j**q)for k in c for q in range(4)}if-~k}
		if c in s:return-1
		s+=[c];I+=1
	return I

Cobalah online!

-41 byte terima kasih kepada ovs
-1 byte terima kasih kepada Jonathan Frech

HyperNeutrino
sumber
Tidak if k+1mungkin if-~k?
Jonathan Frech
@ JonathanFrech ya, terima kasih
HyperNeutrino
2

C #, 461 418 byte

Ini hanya implementasi referensi non-kompetitif untuk (semoga) menghidupkan kembali tantangan ini:

Ditarik oleh Kevin Cruijssen

int P(string[]C){int w=C[0].Length,i=0,l=c.Length;var c=string.Join("",C);var h=new int[l];for(var n=new List<int>();i<l;n.Add(i++))h[i]=c[i]!='@'?int.MaxValue:0;for(i=1;;i++){var t=n;n=new List<int>();foreach(int x in t){foreach(int d in new[]{-1,1,-w,w}){for(int j=x+d;c[j]==' ';j+=d);if(c[j]=='#'&h[j-d]>s){h[j-d]=s;n.Add(j-d);}if(c[j]=='.'&h[j]>s){h[j]=s;n.Add(j);}if(c[j]=='o')return s;}}if(n.Count<1)return -1;}}

Tidak disatukan

int IceGolf(string[] course)
{
    // Width of the course
    int w = course[0].Length;

    // Course as single string
    var c = string.Join("", course);

    // Array of hits per field
    var hits = new int[c.Length];

    // Fields to continue from
    var nextRound = new List<int>();

    // Initialize hits
    for (int i = 0; i < hits.Length; i++)
    {
        if (c[i] != '@')
            // All fields start with a high value
            hits[i] = Int32.MaxValue;
        else
        {
            // Puck field starts with 0
            hits[i] = 0;
            nextRound.Add(i);
        }
    }

    for (int s = 1; ; s++)
    {
        // clear the fields that will be used in the next iteration
        var thisRound = nextRound;
        nextRound = new List<int>();

        foreach (int i in thisRound)
        {
            // test all 4 directions
            foreach (int d in new[] { -1, 1, -w, w })
            {
                int j = i+d;

                // ICE - slide along
                while (c[j] == ' ')
                    j += d;

                // WALL - stop on previous field
                if (c[j] == '#' && hits[j-d] > s)
                {
                    hits[j-d] = s;
                    nextRound.Add(j-d);
                }

                // SAND - stop
                if (c[j] == '.' && hits[j] > s)
                {
                    hits[j] = s;
                    nextRound.Add(j);
                }

                // HOLE return strikes
                if (c[j] == 'o')
                    return s;
            }
        }

        // No possible path found
        if (nextRound.Count == 0)
            return -1;
    }
}

Cobalah online

Manfred Radlwimmer
sumber
1
Golf sedikit lebih: int P(string[]C){int w=C[0].Length,i=0,l=c.Length;var c=string.Join("",C);var h=new int[l];for(var n=new List<int>();i<l;n.Add(i++))h[i]=c[i]!='@'?int.MaxValue:0;for(i=1;;i++){var t=n;n=new List<int>();foreach(int x in t){foreach(int d in new[]{-1,1,-w,w}){for(int j=x+d;c[j]==' ';j+=d);if(c[j]=='#'&h[j-d]>s){h[j-d]=s;n.Add(j-d);}if(c[j]=='.'&h[j]>s){h[j]=s;n.Add(j);}if(c[j]=='o')return s;}}if(n.Count<1)return -1;}}(418 bytes). Juga, bisakah Anda menambahkan tautan TIO dengan kode uji?
Kevin Cruijssen
Terima kasih atas tautan TIO. Kode yang saya berikan di atas tidak berfungsi, jadi saya memperbaikinya, dan bermain golf tiga byte lagi. Cobalah secara online 415 byte . (Anda harus menambahkan kembali kotak uji besar Anda lagi dari TIO Anda saat ini. Saya tidak dapat menempelkan tautan dalam komentar ini karena tautannya terlalu besar dengan kotak uji itu ..; p)
Kevin Cruijssen