Expressar um número
Nos anos 60, os franceses inventaram o programa de TV "Des Chiffres et des Lettres" (Dígitos e letras). O objetivo da parte Dígitos do programa era chegar o mais próximo possível de um determinado número-alvo de três dígitos, usando alguns números selecionados aleatoriamente. Os participantes poderiam usar os seguintes operadores:
- concatenação (1 e 2 são 12)
- adição (1 + 2 é 3)
- subtração (5 - 3 = 2)
- divisão (8/2 = 4); divisão só é permitida se o resultado for um número natural
- multiplicação (2 * 3 = 6)
- parênteses, para substituir a precedência regular das operações: 2 * (3 + 4) = 14
Cada número dado pode ser usado apenas uma vez ou não.
Por exemplo, o número de destino 728 pode ser correspondido exatamente com os números: 6, 10, 25, 75, 5 e 50 com a seguinte expressão:
75 * 10 - ( ( 6 + 5 ) * ( 50 / 25 ) ) = 750 - ( 11 * 2 ) = 750 - 22 = 728
Nesse desafio de código, você terá a tarefa de encontrar uma expressão o mais próximo possível de um determinado número de destino. Como vivemos no século XXI, apresentaremos números-alvo maiores e mais números para trabalhar do que nos anos 60.
Regras
- Operadores permitidos: concatenação, +, -, /, *, (e)
- O operador de concatenação não possui símbolo. Apenas concatene os números.
- Não há "concatenação inversa". 69 é 69 e não pode ser dividido em 6 e 9.
- O número de destino é um número inteiro positivo e tem um máximo de 18 dígitos.
- Existem pelo menos dois números para trabalhar e no máximo 99 números. Esses números também são números inteiros positivos com um máximo de 18 dígitos.
- É possível (na verdade, muito provavelmente) que o número alvo não possa ser expresso em termos de números e operadores. O objetivo é chegar o mais próximo possível.
- O programa deve terminar em um tempo razoável (alguns minutos em um PC de mesa moderno).
- Aplicam-se brechas padrão.
- Seu programa pode não estar otimizado para o conjunto de testes na seção "pontuação" deste quebra-cabeça. Reservo-me o direito de alterar o conjunto de testes se suspeitar que alguém esteja violando essa regra.
- Este não é um codegolf.
Entrada
A entrada consiste em uma matriz de números que pode ser formatada de qualquer maneira conveniente. O primeiro número é o número de destino. O restante dos números são os números com os quais você deve trabalhar para formar o número de destino.
Resultado
Os requisitos para a saída são:
- Deve ser uma string que consiste em:
- qualquer subconjunto dos números de entrada (exceto o número de destino)
- qualquer número de operadores
- Prefiro que a saída seja uma única linha sem espaços, mas se for necessário, você poderá adicionar espaços e novas linhas como achar melhor. Eles serão ignorados no programa de controle.
- A saída deve ser uma expressão matemática válida.
Exemplos
Para facilitar a leitura, todos esses exemplos têm uma solução exata e cada número de entrada é usado exatamente uma vez.
Entrada: 1515483, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
Saída:111*111*(111+11+1)
Entrada: 153135, 1, 2, 3, 4, 5, 6, 7, 8, 9
Saída:123*(456+789)
Entrada: 8888888888, 9, 9, 9, 99, 99, 99, 999, 999, 999, 9999, 9999, 9999, 99999, 99999, 99999, 1
Saída:9*99*999*9999-9999999-999999-99999-99999-99999-9999-999-9-1
Entrada: 207901, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0
Saída:1+2*(3+4)*(5+6)*(7+8)*90
Entrada: 34943, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0
Saída: 1+2*(3+4*(5+6*(7+8*90)))
Mas também a saída válida é:34957-6-8
Pontuação
A pontuação da penalidade de um programa é a soma dos erros relativos das expressões para o conjunto de testes abaixo.
Por exemplo, se o valor alvo for 125 e sua expressão der 120, sua pontuação de penalidade será abs (1 - 120/125) = 0,04.
O programa com a pontuação mais baixa (menor erro relativo total) vence. Se dois programas terminarem igualmente, a primeira inscrição vence.
Finalmente, o conjunto de testes (8 casos):
14142, 10, 11, 12, 13, 14, 15
48077691, 6, 9, 66, 69, 666, 669, 696, 699, 966, 969, 996, 999
333723173, 3, 3, 3, 33, 333, 3333, 33333, 333333, 3333333, 33333333, 333333333
589637567, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
8067171096, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199
78649377055, 0, 2, 6, 12, 20, 30, 42, 56, 72, 90, 110, 132, 156, 182, 210, 240, 272, 306, 342, 380, 420, 462, 506, 552, 600, 650, 702, 756, 812, 870, 930, 992
792787123866, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169
2423473942768, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 2000000, 5000000, 10000000, 20000000, 50000000
Puzzles semelhantes anteriores
Depois de criar esse quebra-cabeça e publicá-lo na caixa de areia, notei algo semelhante (mas não o mesmo!) Em dois quebra-cabeças anteriores: aqui (sem soluções) e aqui . Esse quebra-cabeça é um pouco diferente, porque apresenta o operador de concatenação, não procuro uma correspondência exata e gosto de ver estratégias para chegar perto da solução sem força bruta. Eu acho que é desafiador.
fonte
Respostas:
C ++ 17, pontuação .0086
Este programa tem pontuação de penalidade não determinística devido a corridas de threads, então estou declarando com base em uma média de três execuções, cada uma das quais lidou com a suíte de testes em menos de um minuto:
Aqui está o programa; explicação é fornecida nos comentários. Você pode definir
CONCAT_NONE
regras de contagem regressiva tradicionais que não permitem concatenação ouCONCAT_DIGITS
concatenação dos valores de entrada, mas não de resultados intermediários. Por padrão, sem nenhum dos definidos, as regras mais liberais são usadas.Compilei isso usando o GCC 6.2, usando
g++ -std=c++17 -fopenmp -march=native -O3
(junto com algumas opções de depuração e aviso).fonte
Python 2.7. Pontuação: 1,67039106
Então, eu decidi jogar sozinho. Nada muito chique. Este programa classifica os números na ordem inversa (grande a pequena) e tenta todos os operadores seqüencialmente nos números. Extremamente rápido, mas um desempenho que merece ser substituído.
Aqui está o programa:
A saída para todos os casos de teste é:
fonte