Défi de golf sur glace


24

Le but de ce défi est d'écrire un programme ou une fonction qui renvoie le moins de coups nécessaires pour terminer un cours donné.

Contribution

  • La disposition du cours peut être transmise de la manière et du format que vous préférez. (lu à partir de la console, passé en tant que paramètre d'entrée, lu à partir d'un fichier ou de tout autre, chaîne de lignes multiples, tableau de chaînes, tableau de caractères / octets bidimensionnel).
  • La position de départ de la balle et le trou peuvent également être passés en entrée, il n'est pas nécessaire de les analyser à partir de l'entrée. Dans les cas de test, ils sont inclus dans le cours pour s'assurer qu'il n'y a pas de confusion sur la position réelle.
  • Vous pouvez remapper les caractères saisis vers autre chose, tant qu'ils sont toujours reconnaissables comme des caractères distincts (par exemple, des caractères ASCII imprimables).

Sortie

  • Le programme doit renvoyer le score le plus bas possible (le moins de frappes nécessaires pour atteindre le trou) pour tout cours passé en entrée dans un format raisonnable (chaîne, entier, flottant ou haïku décrivant le résultat)
  • Si le parcours est impossible à battre, revenez -1(ou toute autre valeur falsifiée de votre choix qui ne serait pas retournée pour un parcours battable).

Exemple:

Dans cet exemple, les positions sont notées basées sur 0, X / Y, de gauche à droite, de haut en bas - mais vous pouvez utiliser n'importe quel format que vous aimez car le résultat est de toute façon complètement indépendant du format.

Contribution:

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

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

Sortie:

8

Exemple de cours

Règles et champs

Le cours peut comprendre les champs suivants:

  • '@' Ballon - Le début du cours
  • 'o' Hole - Le but du cours
  • '#' Mur - La balle s'arrêtera lorsqu'elle heurtera un mur
  • '~' Eau - À éviter
  • '.' Sable - La balle s'arrêtera immédiatement sur le sable
  • ' ' Glace - La balle continuera de glisser jusqu'à ce qu'elle touche quelque chose

Les règles de base et les restrictions du jeu:

  • Le ballon ne peut pas se déplacer en diagonale, seulement à gauche, à droite, de haut en bas.
  • La balle ne s'arrêtera pas devant l'eau, seulement devant les murs, sur le sable et dans le trou.
    • Les coups de feu dans l'eau sont invalides / impossibles
    • La balle restera dans le trou, ne la sautera pas comme sur la glace
  • Le parcours est toujours rectangulaire.
  • Le parcours est toujours bordé d'eau ou de murs (aucun contrôle des limites requis).
  • Il y a toujours exactement une balle et un trou.
  • Il n'est pas possible de battre tous les parcours.
  • Il peut y avoir plusieurs chemins qui donnent le même score (le plus bas).

Échappatoires et conditions gagnantes

  • Les failles standard sont interdites
  • Les programmes doivent se terminer
  • Vous ne pouvez pas inventer de règles supplémentaires (frapper la balle si fort qu'elle saute sur l'eau, rebondit sur un mur, saute par-dessus des champs de sable, des courbes dans les coins, etc.)
  • Il s'agit de , donc la solution avec le moins de caractères l'emporte.
  • Les solutions doivent être capables de gérer tous les cas de test fournis, si cela est impossible en raison des restrictions de la langue utilisée, veuillez le préciser dans votre réponse.

Cas de test

Cours # 1 (2 grèves)

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

Cours # 2 (pas possible)

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

Cours # 3 (3 grèves)

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

Cours # 4 (2 grèves)

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

Cours # 5 (pas possible)

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

Plus de cas de test:

https://pastebin.com/Azdyym00


1
Connexes: un , deux .
AdmBorkBork

Si nous utilisons un tableau d'octets à deux dimensions en entrée, sommes-nous autorisés à utiliser un mappage personnalisé pour les symboles?
Arnauld

@Arnauld Je ne sais pas quel est le consensus habituel à ce sujet ici, mais je dirais que c'est ok tant que l'entrée est toujours reconnaissable. J'ai mis à jour la section Input .
Manfred Radlwimmer

Si vous saisissez directement la destination, pouvons-nous exiger que le lieu de destination soit le symbole «sable»?
l4m2

@ l4m2 Bien sûr, cela resterait cohérent avec toutes les autres règles.
Manfred Radlwimmer

Réponses:


6

JavaScript (ES6), 174 octets

Prend la saisie dans la syntaxe de curling curling([x, y])(a) , où x et y sont les coordonnées indexées 0 de la position de départ et a [] est une matrice d'entiers, avec 0= glace, 1= mur, 2= sable, 3= trou et 4= eau

Retourne 0s'il n'y a pas de solution.

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

Essayez-le en ligne!

Commenté

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 octets

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

Essayez-le en ligne!

-41 octets grâce aux ovs
-1 octet grâce à Jonathan Frech


Ça if k+1ne pouvait pas être if-~k?
Jonathan Frech

@JonathanFrech oui, merci
HyperNeutrino

2

C #, 461 418 octets

Il s'agit simplement d'une implémentation de référence non compétitive pour (espérons-le) relancer ce défi:

Golfé par 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;}}

Non golfé

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

Essayez-le en ligne


1
Golfé un peu plus: 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 octets). De plus, pourriez-vous peut-être ajouter un lien TIO avec un code de test?
Kevin Cruijssen

Merci pour le lien TIO. Le code que j'ai fourni ci-dessus ne fonctionnait pas, je l'ai donc corrigé et j'ai joué trois octets de plus. Essayez-le en ligne 415 octets . (Vous devrez à nouveau ajouter votre énorme cas de test à partir de votre TIO actuel. Je n'ai pas pu coller le lien dans ce commentaire parce que le lien était trop gros avec ce cas de test ..; p)
Kevin Cruijssen
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.