Imaginez le scénario suivant: vous jouez à des cuirassés avec un ami mais décidez de tricher. Plutôt que de déplacer un navire après qu'il ait abattu votre navire là où vous vous trouviez, vous décidez de ne placer aucun navire. Vous lui dites que tous ses coups sont ratés, jusqu'à ce qu'il soit impossible de placer les navires de cette manière.
Vous devez écrire une fonction, ou un programme complet, qui prend en quelque sorte 3 arguments: la taille du champ, une liste des quantités de tailles de vaisseaux et une liste de plans.
Champ de bataille
L'un des paramètres donnés est la taille du tableau. Le champ de bataille est un carré de cellules, et le paramètre donné est simplement un côté du carré.
Par exemple, voici un tableau de taille 5.
Les coordonnées du champ sont spécifiées en tant que chaîne à 2 composants: une lettre suivie d'un nombre. Vous pouvez compter sur les lettres dans certains cas.
Lettre spécifie la colonne, nombre spécifie la ligne de la cellule (indexé 1). Par exemple, dans l'image ci-dessus, la cellule en surbrillance est désignée par "D2"
.
Comme il n'y a que 26 lettres, le champ ne peut pas dépasser 26x26.
Navires
Les navires sont des lignes droites de 1 ou plusieurs blocs. La quantité de navires est spécifiée dans une liste, où le premier élément est la quantité de navires à une cellule, le deuxième - de navires à deux cellules, etc.
Par exemple, la liste [4,1,2,0,1]
créerait l’ensemble de navires suivant:
Lorsqu'ils sont placés sur le champ de bataille, les navires ne peuvent pas se croiser ni même se toucher. Pas même avec les coins. Ils peuvent cependant toucher les bords du champ.
Vous trouverez ci-dessous un exemple de placement de navire valide:
Vous pouvez supposer que pour un ensemble de navires donné, il existe toujours un emplacement sur un tableau vide de taille donnée.
Sortie
Si de tels emplacements de navires existent, vous devez en générer un.
Le programme doit générer une matrice de caractères ascii séparés de 3 nouvelles lignes, une pour indiquer une cellule vide, une autre pour une pièce de navire et une autre pour une cellule marquée comme "manquante". Aucun autre caractère ne doit être sorti.
Par exemple,
ZZ@Z
\@@Z
@\\Z
\Z\\
(Dans cet exemple, j'ai défini @
être une cellule vide, \
une cellule "manquée" et Z
une pièce du navire)
Si ce type de placement n'existe pas, le programme / la fonction doit revenir sans rien générer.
Contribution
Si vous décidez de créer un programme complet, c'est à vous de spécifier comment les listes sont entrées, certaines peuvent passer par des arguments, d'autres via stdin.
C'est le code-golf , le plus petit nombre de personnages gagne.
Vous trouverez ici un exemple de solution optimisée sans golf .
Compilez avec -std=c99
, le premier argument est la taille du tableau, les autres arguments sont les tailles de navire. Une liste de plans séparés par une nouvelle ligne est donnée sur stdin. Exemple:
./a 4 1 1 1 <<< $'A2\nA4\nB3\nC3\nC4\D4'
la source
26x26
? J'ai esquissé une solution basée sur les expressions rationnelles et la récursivité, et elle devient extrêmement lente = inutilisable pour les champs plus que6x6
. Soit je fais quelque chose de très stupide, ou le manque de réponses signifie que les autres n'ont pas de succès aussi.10x10
un ensemble de4,3,2,1
naviresRéponses:
GolfScript, 236 caractères
L'entrée est donnée sur STDIN. La première ligne contient la taille et le nombre de navires, chacun suivant les coordonnées de ligne d'un seul coup.
Exemple:
Je pensais que ce défi devrait également avoir au moins une réponse GolfScript. En fin de compte, il est devenu très dépourvu de sens en raison de l’algorithme utilisé, qui privilégie la performance à la brièveté.
Code annoté:
la source
SWI-Prolog,
536441 1 octet1 fin de ligne UNIX, nouvelle ligne finale non comptée
La version avec toutes les optimisations supprimées ( 441 octets):
Étant donné que le code est modifié pour réduire le nombre d'octets, il n'acceptera plus une liste de plans comportant des doublons.
La version avec optimisation de base, entièrement golfée ( 536 → 506 octets)
J'implémente quelques vérifications de base ( nombre de blocs de navires nécessaires ) pour accélérer la sortie du code dans des cas clairement impossibles. Le code est également immunisé contre les doublons dans la liste des prises de vues jusqu'à présent.
Ci-dessous, la version (quelque peu) lisible, avec des commentaires détaillés:
Format de requête:
Exemple de requête (utilisant l'exemple de la question):
la source
Matlab - 536 caractères
Mise à jour: format de sortie beaucoup plus petit, certains espaces de boucle supprimés.
Mise à jour: Version golfée ajoutée
Mise à jour: version commentée ajoutée, version jouée au golf réduite de ~ 100 caractères
Voici la version golfée.
Voici quelques exemples.
La grande ligne avec 'kron' (près du bas du code sans golf) est ma partie préférée de cela. Il écrit un '1' à tous les emplacements de la carte voisins d'une position donnée. Pouvez-vous voir comment cela fonctionne? Il utilise le produit tensoriel de Kronecker, la multiplication matricielle, et indexe la carte sous forme de tableau linéaire ...
la source
Python, 464 caractères
Entrée (stdin):
Sortie:
Fonctionne avec des entiers contenant des bitmaps de différentes fonctionnalités:
la source
[::-1]
qui le fait d'essayer le navire le plus long en premier. Il fait aussi marche arrière dès qu'il trouve un navire qu'il ne peut pas placer.Python, 562 caractères, -8 avec une sortie laide, +4? pour invocation bash
Remarque: les niveaux de retrait sont espace, tabulation, tabulation + espace, tabulation + tabulation, tabulation + tabulation + espace. Cela évite que quelques caractères utilisent uniquement des espaces.
Utilisation et exemple :
Prend les entrées des arguments de la ligne de commande. Génère un blanc sous forme d'espace, un plan en tant que
.
et en tant@
que partie d'un navire:Si insoluble, n'imprime rien:
Le
2>X
est de supprimer un message d'erreur puisque le programme se termine en lançant une exception. N'hésitez pas à ajouter une pénalité de +4 si cela est jugé juste. Sinon, je devrais faire untry: ... except:0
pour le supprimer, ce qui prendrait de toute façon plus de caractères.Je peux aussi imprimer la sortie sous forme de nombres (
0
,1
et2
) de se raser 8 caractères, mais l' esthétique I de valeur.Explication :
Je représente le tableau sous forme de liste de listes d'entiers de taille 2 supérieure à l'entrée, pour éviter d'avoir à vérifier les limites.
0
représente un espace vide,1
un coup de feu et2
un navire. Je parcours la liste des coupsQ
et marque tous les coups. Je convertis la liste des navires en une liste expliciteX
des navires, par exemple,[4, 0, 2, 0, 1]
devient[5, 3, 3, 1, 1, 1, 1]
. Ensuite, il s’agit d’un simple algorithme de retour en arrière: par ordre de taille décroissant, essayez de placer un navire, puis le reste des navires. Si cela ne fonctionne pas, essayez le prochain emplacement. Dès qu’elle réussit, la liste de naviresX
est nulle et l’accèsX[0]
lève une exception qui quitte le programme. Le reste n'est que du golf lourd (initialement 1615 caractères).la source
Perl,
455 447 437 436 422418Dentelé:
Je pense que cela peut être joué plus loin (par exemple avec
eval<>
une entrée pré-formatée, car je vois que tout va bien (?)), Ainsi que quelques autres choses (50$
sigils? Non, ils resteront).La vitesse, comme je l’ai dit plus tôt, peut être un problème (d’instantané (voir exemple ci-dessous) à très très long), en fonction de l’emplacement de la solution sur l’arbre de récurrence, mais qu’il s’agisse de la vétusté du matériel utilisé. Je ferai la version optimisée plus tard, avec la récursivité et 2-3 autres astuces évidentes.
Il fonctionne comme ceci, 3 lignes étant alimentées par STDIN:
~
est l'océan (solution artistique, n'est-ce pas),o
etx
s sont des navires et des tirs. Les 5 premières lignes reçoivent les informations et préparent notre «champ de bataille».$N
est la taille,@S
est un tableau déroulé de vaisseaux (par exemple,1 1 1 1 2 3 3 5
comme ci-dessus) , et passe à l’itération suivante. Etc.$f
est une chaîne représentant le champ de bataille (lignes avec des nouvelles lignes concaténées). Vient ensuite le sous-programme récursif, qui attend l'état actuel du champ de bataille et la liste des navires restants. Il vérifie de gauche à droite, de haut en bas et tente de placer chaque navire dans chaque position, à la fois horizontalement et verticalement (voir? Il faut optimiser, mais ce sera plus tard). Un navire horizontal est un remplacement évident des expressions rationnelles, un peu plus délicat à la verticale - une manipulation de chaîne de bits à remplacer dans "colonne". En cas de succès (H, V ou les deux), les nouvelles positions inaccessibles sont signalées par!
Edit: OK, voici la version de 594 octets (sans retrait) qui essaie réellement d’être utile (rapide) - optimisée au mieux de mes capacités tout en implémentant les mêmes techniques - récursivité (bien que effectuée manuellement) et expressions rationnelles. Il maintient une "pile" -
@A
- tableau d'états intéressant à explorer. Un «état» correspond à 4 variables: chaîne de champ de bataille actuelle, index à partir duquel commencer à essayer de placer les navires, référence à la liste des navires restants et index du prochain navire à essayer. Au départ, il y a un seul "état" - début de chaîne vide, tous les navires. Lors du match (H ou V, voir ci-dessus), l'état actuel est poussé pour enquêter plus tard, l'état mis à jour (avec un navire placé et les positions inaccessibles marquées) est poussé et le blocage est redémarré. Lorsque la fin de la chaîne du champ de bataille est atteinte sans succès, le prochain état disponible depuis@A
est étudié (le cas échéant).D'autres optimisations sont les suivantes: ne pas redémarrer dès le début de la chaîne, essayer de placer les grands navires en premier, ne pas vérifier les navires de même taille si le précédent a échoué à la même position, + peut-être quelque chose d'autre (comme aucune
$&
variable, etc.)..
OTOH, cela prend toujours une éternité pour un cas impossible
6 5 4 3 2 1
dans l'exemple ci-dessus. Peut-être que la version pratique devrait sortir immédiatement si le tonnage total des navires dépasse la capacité du champ de bataille.la source
Solution C #
la source
size=1 ships={1} moves={"A1"}
.Java, 1178
Ouais beaucoup trop longtemps.
Ungolfed:
Sample-Input
Exemple de sortie
Avec
O
tir manqué#
partie de navire_
tirez ici ensuite ;-)Voir sur ideone.com
Le traitement des entrées attend les espaces autour des nombres /
;
et ne fonctionnera pas autrement.Je place les grands navires en premier car ils ont moins d'endroits où aller. Si vous voulez passer à petits d' abord , vous pouvez remplacer
pop()
parremove(0)
etpush(s)
paradd(0,s)
même que le remplacement de l' un des deux devrait encore donner lieu à un programme valide.Si vous autorisez les navires à se toucher, la
g(int,int)
fonction peut être grandement simplifiée ou supprimée.la source