Ice Golf Challenge


24

L'obiettivo di questa sfida è scrivere un programma o una funzione che restituisca il minor numero di avvertimenti necessari per completare un determinato corso.

Ingresso

  • Il layout del corso può essere passato in qualsiasi modo e formato che preferisci. (letto dalla console, passato come parametro di input, letto da un file o da qualsiasi altra stringa a più righe, array di stringhe, array di caratteri / byte bidimensionali).
  • La posizione iniziale della palla e il foro possono essere passati anche come input, non è necessario analizzarli dall'input. Nei casi di test sono inclusi nel corso per assicurarsi che non ci sia confusione sulla posizione effettiva.
  • È possibile rimappare i caratteri di input a qualcos'altro, purché siano ancora riconoscibili come caratteri distinti (ad esempio caratteri ASCII stampabili).

Produzione

  • Il programma deve restituire il punteggio più basso possibile (minima quantità di strike necessari per raggiungere la buca) per qualsiasi rotta superata come input in un formato sensibile (stringa, numero intero, float o haiku che descriva il risultato)
  • Se il corso è impossibile da battere, ritorna -1(o qualsiasi altro valore di falsa a tua scelta che non verrebbe restituito per un corso battibile).

Esempio:

In questo esempio le posizioni sono annotate in base 0, X / Y, da sinistra a destra, dall'alto in basso - ma è possibile utilizzare qualsiasi formato desiderato poiché il risultato è comunque completamente indipendente dal formato.

Ingresso:

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

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

Produzione:

8

Corso di esempio

Regole e campi

Il corso può consistere nei seguenti campi:

  • '@' Ball - L'inizio del corso
  • 'o' Hole - L'obiettivo del corso
  • '#' Muro : la palla si ferma quando colpisce un muro
  • '~' Acqua - Deve essere evitato
  • '.' Sabbia - La palla si fermerà immediatamente sulla sabbia
  • ' ' Ice - Ball continuerà a scorrere fino a quando non colpisce qualcosa

Le regole e le restrizioni di base del gioco:

  • La palla non può muoversi in diagonale, solo a sinistra, a destra, su e giù.
  • La palla non si fermerà davanti all'acqua, solo davanti alle pareti, sulla sabbia e nella buca.
    • I colpi nell'acqua non sono validi / impossibili
    • La palla rimarrà nella buca, non la salterà come se fosse sul ghiaccio
  • Il corso è sempre rettangolare.
  • Il percorso è sempre delimitato da acqua o muri (non sono richiesti controlli al contorno).
  • C'è sempre esattamente una palla e una buca.
  • Non tutti i corsi sono possibili da battere.
  • Potrebbero esserci più percorsi che portano allo stesso punteggio (più basso).

Scappatoie e condizioni vincenti

  • Sono vietate le scappatoie standard
  • I programmi devono terminare
  • Non puoi inventare regole aggiuntive (colpire la palla così forte da saltare sull'acqua, rimbalzare da un muro, saltare su campi di sabbia, curve agli angoli, ecc.)
  • Questo è , quindi vince la soluzione con il minor numero di caratteri.
  • Le soluzioni devono essere in grado di gestire tutti i casi di test forniti, se ciò è impossibile a causa delle restrizioni della lingua utilizzata, specificarlo nella risposta.

Casi test

Corso n. 1 (2 avvertimenti)

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

Corso n. 2 (non possibile)

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

Corso n. 3 (3 avvertimenti)

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

Corso n. 4 (2 avvertimenti)

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

Corso n. 5 (non possibile)

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

Altri casi di test:

https://pastebin.com/Azdyym00


1
Correlati: uno , due .
AdmBorkBork,

Se utilizziamo un array di byte bidimensionali come input, possiamo utilizzare una mappatura personalizzata per i simboli?
Arnauld,

@Arnauld Non so quale sia il solito consenso al riguardo, ma direi che va bene finché l'input è ancora riconoscibile. Ho aggiornato la sezione Input .
Manfred Radlwimmer

Se inserisci direttamente la destinazione, possiamo richiedere che il luogo di destinazione sia il simbolo 'sabbia'?
l4m2

@ l4m2 Certo, in questo modo rimarrebbe coerente con tutte le altre regole.
Manfred Radlwimmer,

Risposte:


6

JavaScript (ES6), 174 byte

Prende ingresso in arricciare sintassi strigliare ([x, y])(a), dove x ed y sono le coordinate 0 indicizzati della posizione di partenza e un [] è una matrice di numeri interi, con 0= ghiaccio, 1= parete, 2= sabbia, 3= foro e 4= acqua

Restituisce 0se non c'è soluzione.

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

Provalo online!

Commentate

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

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

Provalo online!

-41 byte grazie agli ovs
-1 byte grazie a Jonathan Frech


Non potrebbe if k+1essere if-~k?
Jonathan Frech,

@JonathanFrech sì, grazie
HyperNeutrino,

2

C #, 461 418 byte

Questa è solo un'implementazione di riferimento non competitiva per (si spera) far rivivere questa sfida:

Golfato da 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;}}

Ungolfed

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

Provalo online


1
Golfato un po 'di più: 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 byte). Inoltre, potresti forse aggiungere un collegamento TIO con il codice di test?
Kevin Cruijssen,

Grazie per il link TIO. Il codice che ho fornito sopra non ha funzionato, quindi l'ho corretto e ho giocato a golf altri tre byte. Provalo online 415 byte . (Dovrai aggiungere nuovamente il tuo enorme caso di test dal tuo attuale TIO. Non ho potuto incollare il link in questo commento perché il link era troppo grande con quel caso di test ..; p)
Kevin Cruijssen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.