Numeri di Friedman molto belli


13

Un numero di Friedman è un numero intero positivo uguale a un'espressione non banale che utilizza le proprie cifre in combinazione con le operazioni +, -, *, /, ^, parentesi e concatenazione.

Un Nice Friedman Number è un numero intero positivo uguale a un'espressione non banale che utilizza le proprie cifre in combinazione con le stesse operazioni, con le cifre nell'ordine originale.

Un Very Nice Friedman Number (VNFN), che sto inventando qui, è un Nice Friedman Number che può essere scritto senza le parti meno belle (a mio avviso) di tale espressione. Non sono consentite parentesi, concatenazione e negazione unaria.

Per questa sfida, ci sono tre modi possibili di scrivere un'espressione senza parentesi.

Prefisso: equivale all'associatività di sinistra. Questo tipo di espressione è scritto con tutti gli operatori a sinistra delle cifre. Ogni operatore si applica alle seguenti due espressioni. Per esempio:

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

Un VNFN che può essere scritto in questo modo è 343:

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

Postfix: equivale alla giusta associatività. È proprio come la notazione del prefisso, tranne per il fatto che l'operazione va a destra delle cifre. Ogni operatore si applica alle due espressioni precedenti. Per esempio:

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

Un VNFN che può essere scritto in questo modo è 15655:

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

Infix: la notazione Infix utilizza l'ordine standard delle operazioni per le cinque operazioni. Ai fini della sfida, tale ordine di operazioni sarà definito come segue: ^prima tra parentesi , associativamente a destra. Quindi, tra parentesi *e /contemporaneamente, lasciato associativamente. Infine, tra parentesi +e -contemporaneamente, lasciato associativamente.

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 che può essere scritto in questo modo è 11664:

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

Sfida: dato un numero intero positivo, se può essere espresso come espressione non banale delle proprie cifre in notazione prefisso, infisso o postfisso, genera quell'espressione. In caso contrario, non produrre nulla.

Chiarimenti: se sono possibili più rappresentazioni, è possibile produrre qualsiasi sottoinsieme non vuoto di esse. Ad esempio, 736 è un VNFN:

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

+^736, 7+3^6O entrambi sarebbero tutti uscite accettabili.

Un'espressione "Trivial" indica una che non utilizza alcun operatore. Questo è rilevante solo per numeri di una cifra e significa che i numeri di una cifra non possono essere VNFN. Questo è ereditato dalla definizione di un numero di Friedman.

Le risposte dovrebbero essere eseguite in secondi o minuti su input inferiori a un milione.

Relazionato.

IO: regole IO standard. Programma completo, funzione, verbo o simili. STDIN, riga di comando, argomento della funzione o simile. Per l'output di "Nothing", la stringa vuota, una riga vuota nullo simile e una raccolta vuota vanno bene. L'output può essere una stringa delimitata da un carattere che non può essere in una rappresentazione o può essere una raccolta di stringhe.

Esempi:

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

Punteggio: questo è il codice golf. Vince il minor numero di byte.

Inoltre, se ne trovi uno, ti preghiamo di fornire un nuovo numero Friedman molto bello nella tua risposta.


*(+(*(1,2),3,4)manca un paren vicino, dopo,3
Sparr

Qual è il limite "in secondi o minuti"? Mancano ancora quattro ore a ... molti ... minuti.
Non che Charles

@NotthatCharles 4 ore è troppo. Diciamo 1 ora sulla mia macchina, con un po 'di spazio di manovra. A proposito di numeri a più cifre, questo è ciò a cui mi riferivo per concatenazione inParentheses, concatenation and unary negation are disallowed.
isaacg,

Risposte:


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

Chiama con perl -M5.10.0 scratch.pl 736


risultati

I primi risultati che ho trovato sono:

^+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

Spiegazione

Completamente non golfato

Ho cercato di ripetermi il più possibile per facilitare il golf successivo.

#!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

Come è giocato a golf

  • Rimuovi spazi bianchi e commenti e sostituisci tutti i var con la versione a 1 carattere
  • Avvolgere il programma in $_=q! ... !;eval
  • Estrai le stringhe e sostituiscile in seguito.

Questo dà qualcosa del genere, da cui è possibile rimuovere le interruzioni di riga per il risultato:

$_='
    $_=$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

Grazie per la risposta e congratulazioni per essere al primo posto. A grandi linee, come funziona?
isaacg,

Non conosco il perl, ma sembra che sia possibile estrarre le 3 occorrenze di }globe salvare alcuni byte.
isaacg,

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

Accidenti, così vicino.
isaacg,

4

Solo Ruby 2.1.5 - 213 220 238 + 9 = 247

Non sei sicuro di come Ruby batte Perl, ma qui vai ...

Esegui questo con un flag -rtimeout (e -W0 o invia il tuo stderr altrove).

Per renderlo leggermente più robusto, sostituiscilo send([].methods[81],z-1)con repeated_permutation(z-1)un punteggio extra (quindi, 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)]}

Fondamentalmente, passa attraverso tutte le permutazioni degli operatori e prova infix, postfix e prefisso in quell'ordine. Il dmetodo utilizza evalil secondo parametro per eseguire i calcoli, rilevando eventuali eccezioni DivideByZero o Overflow.

Tuttavia, è necessario inviare stderr a / dev / null, altrimenti evaltalvolta verranno stampati avvisi come (eval):1: warning: in a**b, b may be too big.

Mentre mi sono inventato questo disinteressato, ho trovato un modo per salvare tre personaggi!

Ungolfed (principi obsoleti ma simili):

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 ha reso questo lavoro per numeri più grandi invece di timeout.

220 ha eliminato tre caratteri dichiarando array di parentesi e risolto un bug in cui i numeri a una cifra erano considerati VNFN

213 commit iniziale


Ottima soluzione - completa la magia nera per me! Immagino che il rubino superi il Perl poiché ha funzioni di permutazione e zip integrate.
alexander-brett,

@ alexander-brett meglio? a.zip(b,c)restituisce una matrice di matrici come [ [a[0],b[0],c[0]],[a[1],b[1],c[1]], etc.]e ['hi', 'there']*''concatena semplicemente la rappresentazione in forma di stringa dei valori della matrice.
Non che Charles

oh, e [a,b]*3cede[a,b,a,b,a,b]
Non che 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

provalo qui

http://octave-online.net/


sono necessari ulteriori miglioramenti
Abr001

le persone non sono abituali con matlab qui?
Abr001,

0

Python 2, 303 byte

Provalo online

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

L'output Infix conterrà **invece di ^. Se ciò non è consentito, si .replace('**','^')verificherà e aggiungerà altri 18 byte

Spiegazione:

# 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.