Défi de l'Avent 1: Aidez le Père Noël à déverrouiller son coffre-fort actuel!


18

Suivant >>

Mots-clés descriptifs (pour la recherche): rendre deux matrices équivalentes, chevaucher, tableau, rechercher

Défi

Le Père Noël a eu une histoire d'elfes volant des cadeaux de sa chambre forte dans le passé, donc cette année, il a conçu une serrure qui est très difficile à casser, et il semble avoir empêché les elfes de sortir cette année. Malheureusement, il a perdu la combinaison et il ne sait pas non plus comment l'ouvrir! Heureusement, il vous a engagé pour écrire un programme pour trouver la combinaison. Ce n'est pas nécessairement le plus court, mais il doit le trouver le plus rapidement possible!

Il a un horaire très strict et il ne peut pas se permettre d'attendre très longtemps. Votre score sera la durée d'exécution totale de votre programme multipliée par le nombre d'étapes de sortie de votre programme pour l'entrée de notation. Le score le plus bas l'emporte.

Caractéristiques

Le verrou est une matrice carrée de 1 et de 0. Il est défini sur une disposition aléatoire de 1 et de 0 et doit être défini sur un code spécifié. Heureusement, le Père Noël se souvient du code requis.

Il peut effectuer quelques étapes. Chaque étape peut être effectuée sur n'importe quelle sous-matrice contiguë (c'est-à-dire que vous devez sélectionner une sous-matrice entièrement délimitée par un coin supérieur gauche et inférieur droit) (il peut s'agir d'une sous-matrice non carrée):

  1. Rotation à droite de 90 degrés *
  2. Rotation à gauche de 90 degrés *
  3. Rotation à 180 degrés
  4. Faites défiler les néléments de chaque ligne vers la droite ou vers la gauche (retour à la ligne)
  5. Faire défiler les méléments de chaque colonne vers le haut ou vers le bas (retour à la ligne)
  6. Retourner horizontalement
  7. Retourner verticalement
  8. Retournez sur la diagonale principale *
  9. Retournez l'anti-diagonale principale *

* uniquement si la sous-matrice est carrée

Bien entendu, il peut également effectuer ces étapes sur l'ensemble de la matrice. Étant donné que les 1 et les 0 ne peuvent être échangés que sur la matrice mais que la valeur d'un carré ne peut pas être directement modifiée, le nombre de 1 et de 0 est le même pour la configuration de début et de fin.

Spécifications de formatage + règles

Vous recevrez l'entrée sous forme de deux matrices carrées (position de départ et position de fin) dans le format raisonnable de votre choix. La sortie doit être une séquence de ces étapes dans n'importe quel format lisible. Comme il ne s'agit pas de code-golf, veuillez en faire un format facilement vérifiable, mais ce n'est pas une exigence stricte. Vous pouvez choisir de prendre la longueur latérale des matrices dans l'entrée si vous le souhaitez.

Votre programme sera exécuté sur mon ordinateur (Linux Mint, les détails de la version exacte sont disponibles sur demande si quelqu'un s'en soucie: P) et je le chronométrerai en fonction du temps entre le moment où j'appuie sur "Entrée" sur la ligne de commande et lorsque le la commande se termine.

Cas de test

1 0 0 1    0 0 0 0
0 1 1 0 -> 0 0 0 0
0 1 1 0 -> 1 1 1 1
1 0 0 1    1 1 1 1
  1. Prenez la matrice entière. Faites défiler chaque colonne vers le haut 1.
  2. Prenez les deux colonnes du milieu comme sous-matrice. Faites défiler chaque colonne vers le bas 2.
1 0 1 0 1    0 1 0 1 0
0 1 0 1 0    1 0 1 0 1
1 0 1 0 1 -> 0 1 1 1 0
0 1 0 1 0    1 0 1 0 1
1 0 1 0 1    0 1 0 1 0
  1. Prenez la matrice entière. Faites défiler chaque colonne vers le bas 1.
  2. Prenez la colonne du milieu. Faites-le descendre 2.
  3. Prenez les 2 premières rangées. Retournez-le verticalement.
  4. Prenez les 2 éléments les plus à droite de la rangée supérieure. Échangez-les (tournez à droite / gauche 1, retournez horizontalement).
  5. Prenez les 2 éléments les plus à gauche de la rangée supérieure. Échangez-les.

Il pourrait y avoir des méthodes plus efficaces, mais cela n'a pas d'importance. N'hésitez pas à les signaler dans les commentaires si vous en trouvez un :)

Jugement du cas de test

Ce cas de test sera utilisé pour évaluer votre soumission. Si je pense qu'une réponse est trop spécialisée pour le cas de test, j'ai le droit de repiquer une entrée aléatoire et de juger toutes les réponses avec le nouveau cas. Le cas de test peut être trouvé ici où le haut est le début et le bas est la configuration souhaitée.

Si je pense que les réponses sont trop spécialisées, le MD5 du prochain test est 3c1007ebd4ea7f0a2a1f0254af204eed. (Ceci est écrit ici en ce moment pour me libérer des accusations de tricherie: P)

Des échappatoires standard s'appliquent. Aucune réponse ne sera acceptée. Bon codage!

Remarque: je me suis inspiré de cette série de défis d' Advent Of Code . Je n'ai aucune affiliation avec ce site

Vous pouvez voir une liste de tous les défis de la série en consultant la section 'Linked' du premier défi ici .


Information: Le cas de test a 192 0et 64 1, et il y a des 256 choose 64 ≈ 1.9 × 10⁶¹matrices totales accessibles. (qui est comparable à un Megaminx, et est plus grand qu'un Rubik's Revenge, bien que beaucoup moins qu'un cube de professeur)
user202729

Réponses:


1

Java

import java.util.Arrays;

public class SantaMatrix4 {
	
	public static void flipV(int[][] matrix, int row1, int col1, int row2, int col2) {
		for (int row = row1; row <= (row2 - row1) / 2 + row1; row++) {
			for (int col = col1; col <= col2; col++) {
				int tmp = matrix[row][col];
				matrix[row][col] = matrix[row2 - row + row1][col];
				matrix[row2 - row + row1][col] = tmp;
			}
		}
	}
	
	public static void flipH(int[][] matrix, int row1, int col1, int row2, int col2) {
		for (int row = row1; row <= row2; row++) {
			for (int col = col1; col <= (col2 - col1) / 2 + col1; col++) {
				int tmp = matrix[row][col];
				matrix[row][col] = matrix[row][col2 - col + col1];
				matrix[row][col2 - col + col1] = tmp;
			}
		}
	}

	public static void main(String[] args) {
		int counter = 0;
		int n = Integer.parseInt(args[counter++]);
		int[][] matrix1 = new int[n][n];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				matrix1[i][j] = Integer.parseInt(args[counter++]);
			}
		}
				
		int[][] matrix2 = new int[n][n];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				matrix2[i][j] = Integer.parseInt(args[counter++]);
			}
		}
			
		int[] ops = new int[5 * matrix1.length * matrix1.length * 2];
		int numOps = 0;
		int opsI = 0;
		
		for (int row = 0; row < n; row++) {
			for (int col = 0; col < n; col++) {
				int goal = matrix2[row][col];
				boolean gotIt = false;
				
				//Look for required number to the right
				for (int i = row; i < n && !gotIt; i++) {
					for (int j = col; j < n && !gotIt; j++) {
						if (i == row && j == col) continue;
						if (matrix1[i][j] == goal) {
							flipH(matrix1, row, col, i, j);
							flipV(matrix1, row, col, i, j);
							ops[opsI++] = 1;
							ops[opsI++] = row;
							ops[opsI++] = col;
							ops[opsI++] = i;
							ops[opsI++] = j;
							numOps++;
							
							gotIt = true;
						}
					}
				}

				//Look for required number below and to the left
				for (int i = row + 1; i < n && !gotIt; i++) {
					for (int j = 0; j < col && !gotIt; j++) {
						if (matrix1[i][j] == goal) {
							flipH(matrix1, i, j, i, col);
							ops[opsI++] = 2;
							ops[opsI++] = i;
							ops[opsI++] = j;
							ops[opsI++] = i;
							ops[opsI++] = col;
							
							flipV(matrix1, row, col, i, col);
							ops[opsI++] = 3;
							ops[opsI++] = row;
							ops[opsI++] = col;
							ops[opsI++] = i;
							ops[opsI++] = col;
							
							numOps += 2;
							gotIt = true;
						}
					}
				}
				
			}
		}

		System.out.println(Arrays.toString(ops));
		System.out.println(numOps);
	}
}

Version codée en dur légèrement plus rapide: essayez-la en ligne!

L'entrée est des entiers séparés par des espaces via la ligne de commande. Le premier entier est la largeur des deux matrices. Les entiers restants sont leurs éléments, ligne par ligne.

Chaque permutation d'une matrice peut être obtenue avec uniquement les opérateurs flip horizontal et flip vertical, j'ai donc ignoré le reste, sauf pour remplacer un vFlip et un hFlip consécutifs dans la même région par une rotation de 180 degrés.

Le programme parcourt chaque élément. Chaque fois que nous rencontrons un élément qui a le mauvais bit, il regarde plus loin dans le tableau pour trouver un endroit qui a le bon bit. J'ai divisé la région de recherche en deux: celles avec une coordonnée de colonne égale ou plus grande et celles avec une coordonnée de colonne plus petite. Notez que ce dernier doit avoir une coordonnée de ligne plus grande en fonction de la façon dont nous traversons le tableau. Si nous trouvons un bit correct dans la première région de recherche, nous pouvons simplement faire pivoter de 180 degrés la sous-matrice couvrant les deux éléments pour un total d'une opération. S'il se trouve dans la deuxième région, nous pouvons utiliser un retournement horizontal pour déplacer le bit correct dans la même colonne que le mauvais bit, puis retourner verticalement la sous-matrice couvrant les deux pour un total de deux opérations.

Le résultat du programme est un tableau qui doit être divisé mentalement en groupes de cinq. Chaque groupe est (i, row1, col1, row2, col2) où i est 0 pour un no-op, 1 pour une rotation de 180 degrés, 2 pour un flip horizontal et 3 pour un flip vertical. Les 4 autres composants décrivent la région sur laquelle l'opération s'exécute. Je ne suis pas sûr que ce soit un format lisible.

Pour le cas de test donné, j'obtiens 258 opérations et deux à trois millisecondes sur mon ordinateur.


@Erik the Outgolfer Ce n'était pas spécifié, et le codage en dur le rend plus facile à juger.
WhatToDo

Je l'ai changé pour prendre l'entrée de la ligne de commande
WhatToDo

Ce format de sortie est assez raisonnable. Je reçois cependant 1000 numéros dans le tableau (200 opérations?), D'où vient le 258? Je suis un peu confus quant à la façon de lire la sortie de ceci: P
HyperNeutrino

Lorsque je l'exécute, j'obtiens une longueur de 1290 (jusqu'au début des opérations sans opération), soit cinq fois le nombre d'opérations. Le 258 n'est que le nombre d'opérations.
WhatToDo
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.