Très beaux numéros de Friedman


13

Un nombre de Friedman est un entier positif qui est égal à une expression non triviale qui utilise ses propres chiffres en combinaison avec les opérations +, -, *, /, ^, les parenthèses et la concaténation.

Un nombre de Nice Friedman est un entier positif qui est égal à une expression non triviale qui utilise ses propres chiffres en combinaison avec les mêmes opérations, avec les chiffres dans leur ordre d'origine.

Un Very Nice Friedman Number (VNFN), que j'invente ici, est un Nice Friedman Number qui peut être écrit sans les parties les moins jolies (à mon avis) d'une telle expression. Les parenthèses, la concaténation et la négation unaire sont interdites.

Pour ce défi, il existe trois façons possibles d'écrire une expression sans parenthèses.

Préfixe: cela équivaut à l'associativité de gauche. Ce type d'expression est écrit avec tous les opérateurs à gauche des chiffres. Chaque opérateur s'applique aux deux expressions suivantes. Par exemple:

*+*1234 = *(+(*(1,2),3),4) = (((1*2)+3)*4) = 20

Un VNFN qui peut être écrit de cette façon est 343:

^+343 = ^(+(3,4),3) = ((3+4)^3) = 343

Postfix: c'est l'équivalent de l'associativité droite. C'est comme la notation de préfixe, sauf que l'opération va à droite des chiffres. Chaque opérateur s'applique aux deux expressions précédentes. Par exemple:

1234*+* = (1,(2,(3,4)*)+)* = (1*(2+(3*4))) = 14

Un VNFN qui peut être écrit de cette façon est le 15655:

15655^+** = (1,(5,(6,(5,5)^)+)*)* = (1*(5*(6+(5^5)))) = 15655

Infix: la notation Infix utilise l'ordre standard des opérations pour les cinq opérations. Aux fins du défi, cet ordre d'opérations sera défini comme suit: Parenthèse d' ^abord, à droite de manière associative. Ensuite, entre parenthèses *et /simultanément, à gauche de manière associative. Enfin, entre parenthèses +et -simultanément, laissé associativement.

1-2-3 = (1-2)-3 = -4
2/3*2 = (2/3)*2 = 4/3
2^2^3 = 2^(2^3) = 256
1^2*3+4 = (1^2)*3+4 = 7

Un VNFN qui peut être écrit de cette façon est 11664:

1*1*6^6/4 = (((1*1)*(6^6))/4) = 11664

Défi: étant donné un entier positif, s'il peut être exprimé comme une expression non triviale de ses propres chiffres dans la notation préfixée, infixée ou postfixée, affichez cette expression. Sinon, ne rien produire.

Clarifications: si plusieurs représentations sont possibles, vous pouvez en sortir n'importe quel sous-ensemble non vide. Par exemple, 736 est un VNFN:

+^736 = 736
7+3^6 = 736

+^736, 7+3^6 ou les deux seraient tous des sorties acceptables.

Une expression "triviale" signifie une expression qui n'utilise aucun opérateur. Cela ne concerne que les numéros à un chiffre et signifie que les numéros à un chiffre ne peuvent pas être des VNFN. Ceci est hérité de la définition d'un nombre de Friedman.

Les réponses devraient s'exécuter en quelques secondes ou minutes sur des entrées inférieures à un million.

En relation.

IO: règles d'E / S standard. Programme complet, fonction, verbe ou similaire. STDIN, ligne de commande, argument de fonction ou similaire. Pour la sortie de "Nothing", la chaîne vide, une ligne vierge nullou similaire et une collection vide conviennent parfaitement. La sortie peut être une chaîne délimitée avec un caractère qui ne peut pas être dans une représentation, ou peut être une collection de chaînes.

Exemples:

127
None

343
^+343

736
736^+
7+3^6

2502
None

15655
15655^+**

11664
1*1*6^6/4
1^1*6^6/4

5
None

Notation: Il s'agit du code golf. Le moins d'octets gagne.

De plus, si vous en trouvez un, veuillez donner un nouveau numéro de Friedman très agréable dans votre réponse.


*(+(*(1,2),3,4)manque une parenthèse rapprochée, après,3
Sparr

Quel est le plafond "en quelques secondes ou minutes"? Quatre heures, c'est encore ... beaucoup ... de minutes.
Pas que Charles

@NotthatCharles 4 heures, c'est trop. Disons 1 heure sur ma machine, avec une marge de manœuvre. À propos des nombres à plusieurs chiffres, c'est à cela que je faisais référence par concaténation dansParentheses, concatenation and unary negation are disallowed.
isaacg

Réponses:


5

Perl, 345 334 318 293 263 245B

$_='$_=$i=pop;$c=y///c-1;sub f{say if$c&&$i==eval pop=~s/\^/**/gr}A$m)$1$4"})};f"("x$c.$m}globOx$c.$i;A$1$4($m"})};f$m.")"x$c}glob$i.Ox$c;map{f$_}glob joinO,/./g';s!O!"{+,-,*,/,^}"!g;s!A!'map{m{(\d)((?R)|(\d)(?{$m=$3}))(.)(?{$m="'!ge;s!d!D!;eval

Appeler avec perl -M5.10.0 scratch.pl 736


Résultats

Les premiers résultats que j'ai trouvés sont:

^+343
736^+
7+3^6
^+/3125
^+^3125
/^+-11664
/^--11664
1-1+6^6/4
/^++14641
^^++14641
1+5^6/1-8
1+5^6^1-8
1+5^6-2-2
1+5^6-2^2
1+5^6+2-4
1+5^6+4^2
-^+^16377
-^-+16377
/^+^16384
/^-+16384

Explication

Entièrement non golfé

J'ai essayé de me répéter autant que possible pour faciliter le golf ultérieur.

#!perl
use 5.10.0;

$_ = $input = pop;

# y///c counts characters in $_
$count = y///c - 1;

sub f {
    say if $count && $input == eval pop =~ s/\^/**/gr
}

# PREFIX
map {
    m{                            # Parses *^+1234
        (\D)                      # $1 = first symbol
        (
            (?R)                  # RECURSE
        |
            (\d)(?{               # $3 = first digit
                $match=$3
            })
        )
        (.)(?{                    # $4 = last digit
            $match="$match)$1$4"
        })
    }x;
    f "(" x $count . $match
}
    # glob expands '{0,1}{0,1}' into 00,01,10,11
    glob "{+,-,*,/,^}" x $count . $input;

# POSTFIX
map {
    m{(\d)((?R)|(\d)(?{$match=$3}))(.)(?{$match="$1$4($match"})};
    f $match. ")" x $count
}
    glob $input . "{+,-,*,/,^}" x $count;

# INFIX
# /./g splits $_ into characters
map { f $_} glob join "{+,-,*,/,^}", /./g

Comment c'est joué

  • Supprimer les espaces et les commentaires et remplacer tous les vars par une version à 1 caractère
  • Envelopper le programme dans $_=q! ... !;eval
  • Extraire les chaînes et les remplacer par la suite.

Cela donne quelque chose comme ça, à partir duquel vous pouvez supprimer les sauts de ligne pour le résultat:

$_='
    $_=$i=pop;
    $c=y///c-1;
    sub f{say if$c&&$i==eval pop=~s/\^/**/gr}
    A$m)$1$4"})};f"("x$c.$m}globOx$c.$i;
    A$1$4($m"})};f$m.")"x$c}glob$i.Ox$c;
    map{f$_}glob joinO,/./g
';
s!O!"{+,-,*,/,^}"!g;
s!A!'map{m{(\d)((?R)|(\d)(?{$m=$3}))(.)(?{$m="'!ge;
s!d!D!;
eval

Merci pour la réponse et félicitations pour votre première place. Dans les grèves larges, comment ça marche?
isaacg

Je ne connais pas perl, mais il semble qu'il pourrait être possible d'extraire les 3 occurrences de }globet de sauvegarder quelques octets.
isaacg

s!B!}glob!g;BBB-> 15B; }glob}glob}glob-> 15B :)
alexander-brett

Zut, si proche.
isaacg

4

Ruby 2.1.5 uniquement - 213 220 238 + 9 = 247

Je ne sais pas comment Ruby bat Perl, mais c'est parti ...

Exécutez cela avec un indicateur -rtimeout (et -W0 ou envoyez votre stderr ailleurs).

Pour rendre cela légèrement plus robuste, remplacez send([].methods[81],z-1)par repeated_permutation(z-1)et marquez un caractère supplémentaire (donc, 248 ).

g=$*[0].split //
exit if 2>z=g.size
d=->a,s{$><<a*''&&exit if$*[0].to_i==timeout(2){eval"#{(s*'').gsub(?^,'**')}"}rescue p}
l,r=[?(]*z,[?)]*z
%w{* / + - ^}.send([].methods[81],z-1){|o|d[m=g.zip(o),m]
d[g+o,l.zip(m)+r]
d[o+g,l+g.zip(r,o)]}

Fondamentalement, parcourez toutes les permutations des opérateurs et essayez infixe, suffixe et préfixe dans cet ordre. La dméthode utilise evalle deuxième paramètre pour effectuer les calculs, intercepter toutes les exceptions DivideByZero ou Overflow.

Vous devez cependant envoyer stderr vers / dev / null, sinon eval, des avertissements seront parfois affichés comme (eval):1: warning: in a**b, b may be too big.

Alors que je suis venu avec ce non-golf, j'ai trouvé un moyen de sauver trois caractères!

Non golfé (principes obsolètes mais similaires):

input = $*[0]
digits = input.split //
num_digits = digits.size
exit if 2 > num_digits # one-digit numbers should fail

def print_if_eval print_array, eval_array
  # concatenate the array and replace ^ with **
  eval_string = (eval_array * '').gsub(?^, '**') 
  val = eval(eval_string)
  if input.to_i == val
    $><<print_array*''
    exit
  end
rescue
  # this catches any DivideByZero or Overflow errors in eval.
end
# technically, this should be * (num_digits - 1), but as long as we 
# have AT LEAST (num_digits - 1) copies of the operators, this works
operators = %w{* / + - ^} * num_digits
left_parens = ['('] * num_digits
right_parens = [')'] * num_digits
operators.permutation(num_digits-1) { |op_set|
  # infix
  # just uses the native order of operations, so just zip it all together
  # 1+2-3*4/5^6
  print_if_eval(digits.zip(op_set),
                digits.zip(op_set))

  # postfix
  # leftparen-digit-operator, repeat; then add right_parens
  # (1+(2-(3*(4/(5^(6))))))
  # 
  print_if_eval(digits+op_set,
                (left_parens.zip(digits, op_set) + right_parens))

  # prefix
  # leftparens; then add digit-rightparen-operator, repeat
  # ((((((1)+2)-3)*4)/5)^6)
  print_if_eval(op_set+digits,
                left_parens + digits.zip(right_parens, op_set))
}

Changelog

247 a fait ce travail pour un plus grand nombre au lieu de temporiser.

220 a rasé trois caractères en déclarant des tableaux de paren et a corrigé un bogue où les nombres à un chiffre étaient considérés comme des VNFN

213 validation initiale


Grande solution - complète la magie noire pour moi! Je suppose que ruby ​​bat Perl car il a des fonctions intégrées de zip et de permutation.
alexander-brett

@ alexander-brett mieux? a.zip(b,c)renvoie un tableau de tableaux comme [ [a[0],b[0],c[0]],[a[1],b[1],c[1]], etc.]et ['hi', 'there']*''concatène simplement la représentation sous forme de chaîne des valeurs du tableau.
Pas que Charles

oh, et [a,b]*3cède[a,b,a,b,a,b]
Pas que Charles

1

MATLAB (435 b)

n=input('');b=str2num(fliplr(num2str(n)));l=floor(log(b)/log(10));a=unique(nchoosek(repmat('*+-/^', 1,5), l), 'rows');for k=1:numel(a(:,1)),for j=0:2,c=strcat((j>1)*ones(l)*'(',mod(b,10)+48);for i=1:l,c=strcat(c,a(k,i),(j<1)*'(',mod(floor(b/10^i),10)+48,(j>1)*')'); end,c=strcat(c,(j<1)*ones(l)*')');if eval(c(1,:))==n,fprintf('%s%s%s%s\n',c(1,1:(j==1)*numel(c(1,:))),fliplr(a(k,1:(j>1)*l)),(j~=1)*num2str(n),a(k,1:(j<1)*l));end,end,end

essayez-le ici

http://octave-online.net/


encore plus d'améliorations nécessaires
Abr001am

les gens ne sont pas habitués au matlab ici?
Abr001am

0

Python 2, 303 octets

Essayez-le en ligne

from itertools import*
n=input()
l=len(n)-1
E=eval
for c in product('+-*/^',repeat=l):
 L=lambda x,y:x.join(map(y.join,zip(n,c+('',)))).replace('^','**')
 C=''.join(c)
 try:
    if`E(L('',''))`==n:print L('','')
    if`E('('*-~l+L('',')'))`==n:print C[::-1]+n
    if`E(L('(','')+')'*l)`==n:print n+C
 except:pass

La sortie Infix contiendra **au lieu de ^. Si cela n'est pas autorisé, se .replace('**','^')produira et ajoutera 18 octets supplémentaires

Explication:

# get all possible combinations of operators (with repetitions)
product('+-*/^',repeat=l)  

# create string from input and operators like
# if passed '(' and '' will return (a+(b+(c
# if passed '' and ')' will return a)+b)+c)
# if passed '' and '' will return a+b+c
lambda x,y:x.join(map(y.join,zip(n,c+('',)))).replace('^','**')

# evaluate infix
E(L('',''))
# evaluate prefix
E('('*-~l+L('',')')) 
# evaluate postfix
E(L('(','')+')'*l)
# all evals need to be inside try-except to handle possible 0 division

# prefix output is need to be swapped (which IMO is not needed)
n:print C[::-1]+n
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.