Sehr nette Friedman-Zahlen

13

Eine Friedman-Zahl ist eine positive Ganzzahl, die einem nicht trivialen Ausdruck entspricht, der seine eigenen Ziffern in Kombination mit den Operationen +, -, *, /, ^, Klammern und Verkettung verwendet.

Eine Nice Friedman-Zahl ist eine positive Ganzzahl, die einem nicht trivialen Ausdruck entspricht, der seine eigenen Ziffern in Kombination mit denselben Operationen verwendet, wobei die Ziffern in ihrer ursprünglichen Reihenfolge vorliegen.

Eine Very Nice Friedman Number (VNFN), die ich hier erfinde, ist eine Nice Friedman Number, die ohne die (meiner Meinung nach) weniger hübschen Teile eines solchen Ausdrucks geschrieben werden kann. Klammern, Verkettung und unäre Verneinung sind nicht zulässig.

Für diese Herausforderung gibt es drei Möglichkeiten, einen Ausdruck ohne Klammern zu schreiben.

Präfix: Dies entspricht der Linksassoziativität . Diese Art von Ausdruck wird mit allen Operatoren links von den Ziffern geschrieben. Jeder Operator gilt für die folgenden zwei Ausdrücke. Zum Beispiel:

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

Eine VNFN, die auf diese Weise geschrieben werden kann, ist 343:

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

Postfix: Dies entspricht der Rechtsassoziativität. Es ist wie bei der Präfixnotation, nur dass die Operation rechts von den Ziffern steht. Jeder Operator gilt für die beiden vorherigen Ausdrücke. Zum Beispiel:

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

Eine VNFN, die auf diese Weise geschrieben werden kann, ist 15655:

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

Infix: Die Infix-Notation verwendet die Standardreihenfolge für die fünf Operationen. Für die Zwecke der Herausforderung wird diese Operationsreihenfolge wie folgt definiert: Klammern Sie ^zuerst rechts assoziativ ein. Dann in Klammern *und /gleichzeitig assoziativ verlassen. Schließlich in Klammern +und -gleichzeitig assoziativ verlassen.

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

Eine VNFN, die auf diese Weise geschrieben werden kann, ist 11664:

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

Herausforderung: Wenn eine positive Ganzzahl als nicht-trivialer Ausdruck der eigenen Ziffern in Präfix-, Infix- oder Postfix-Notation angegeben werden kann, geben Sie diesen Ausdruck aus. Wenn nicht, nichts ausgeben.

Erläuterungen: Wenn mehrere Darstellungen möglich sind, können Sie eine beliebige nicht leere Teilmenge davon ausgeben. Zum Beispiel ist 736 eine VNFN:

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

+^736, 7+3^6oder beides wären alles akzeptable Ausgaben.

Ein "Trivial" -Ausdruck bedeutet einen Ausdruck, der keine Operatoren verwendet. Dies ist nur für einstellige Nummern relevant und bedeutet, dass einstellige Nummern keine VNFNs sein können. Dies geht aus der Definition einer Friedman-Zahl hervor.

Bei Eingaben unter einer Million sollten die Antworten in Sekunden oder Minuten ausgeführt werden.

Verbunden.

IO: Standard IO-Regeln. Volles Programm, Funktion, Verb oder ähnliches. STDIN, Kommandozeile, Funktionsargument oder ähnliches. Für die Ausgabe von "Nothing" sind die leere Zeichenfolge, eine leere Zeile nulloder ähnliches und eine leere Auflistung in Ordnung. Die Ausgabe kann eine Zeichenfolge sein, die durch ein Zeichen begrenzt ist, das sich nicht in einer Darstellung befindet, oder es kann sich um eine Sammlung von Zeichenfolgen handeln.

Beispiele:

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

Wertung: Dies ist Codegolf. Wenigste Bytes gewinnt.

Wenn Sie eine finden, geben Sie in Ihrer Antwort bitte eine neue Very Nice Friedman-Nummer an.

isaacg
quelle
*(+(*(1,2),3,4)fehlt eine enge paren, nach,3
Sparr
Was ist die Obergrenze für "in Sekunden oder Minuten"? Vier Stunden sind noch in ... vielen ... Minuten.
Nicht dass Charles
@NotthatCharles 4 Stunden ist zu viel. Sagen wir 1 Stunde auf meiner Maschine, mit etwas Wackelraum. Über mehrstellige Zahlen bezog ich mich in der Verkettung aufParentheses, concatenation and unary negation are disallowed.
isaacg

Antworten:

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

Mit anrufen perl -M5.10.0 scratch.pl 736


Ergebnisse

Die ersten Ergebnisse, die ich gefunden habe, sind:

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

Erläuterung

Völlig ungolfed

Ich habe versucht, mich so oft wie möglich zu wiederholen, um das spätere Golfen zu erleichtern.

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

Wie es Golf spielt

  • Entfernen Sie Leerzeichen und Kommentare und ersetzen Sie alle Variablen durch eine 1-Zeichen-Version
  • Programm einwickeln $_=q! ... !;eval
  • Extrahieren Sie die Zeichenfolgen und ersetzen Sie sie anschließend.

Dies ergibt so etwas, von dem Sie die Zeilenumbrüche für das Ergebnis entfernen können:

$_='
    $_=$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
Alexander-Brett
quelle
Vielen Dank für die Antwort und herzlichen Glückwunsch zum ersten Platz. Wie funktioniert es in großen Streiks?
isaacg
Ich kenne Perl nicht, aber es sieht so aus, als ob es möglich wäre, die 3 Vorkommen zu extrahieren }globund einige Bytes zu speichern.
isaacg
s!B!}glob!g;BBB-> 15B; }glob}glob}glob-> 15B :)
Alexander-Brett
Verdammt, so nah.
isaacg
4

Nur Ruby 2.1.5 - 213 220 238 + 9 = 247

Ich bin nicht sicher, wie Ruby Perl schlägt, aber los geht's ...

Führen Sie dies mit einem -rtimeout-Flag aus (und entweder -W0 oder senden Sie Ihr stderr an eine andere Stelle).

Um dies etwas robuster zu machen, ersetzen Sie es send([].methods[81],z-1)durch repeated_permutation(z-1)ein zusätzliches Zeichen und erhalten Sie einen Punkt (also 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)]}

Grundsätzlich sollten Sie alle Permutationen von Operatoren durchgehen und Infix, Postfix und Präfix in dieser Reihenfolge ausprobieren. Die dMethode verwendet evalden zweiten Parameter, um die Berechnungen durchzuführen, wobei alle DivideByZero- oder Überlaufausnahmen abgefangen werden.

Sie müssen jedoch stderr an / dev / null senden, andernfalls evalwerden manchmal Warnungen wie gedruckt (eval):1: warning: in a**b, b may be too big.

Während ich mir dieses Ungolfing ausgedacht habe, habe ich einen Weg gefunden, drei Zeichen zu sparen!

Ungolfed (veraltete, aber ähnliche Prinzipien):

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))
}

Änderungsprotokoll

247 machte diese Arbeit für größere Zahlen, anstatt Zeitüberschreitung.

220 reduzierte drei Zeichen durch Deklarieren von Paren-Arrays und behebte einen Fehler, bei dem einstellige Zahlen als VNFNs angesehen wurden

213 Initial Commit

Nicht dieser Charles
quelle
Tolle Lösung - komplett schwarze Magie für mich! Ich denke, Ruby schlägt Perl, da es integrierte Zip- und Permutationsfunktionen hat.
Alexander-Brett
@ Alexander-Brett Geht es dir besser? a.zip(b,c)Gibt ein Array von Arrays zurück [ [a[0],b[0],c[0]],[a[1],b[1],c[1]], etc.]und ['hi', 'there']*''verkettet nur die String-Darstellung der Array-Werte.
Nicht dass Charles
oh, und [a,b]*3ergibt[a,b,a,b,a,b]
Nicht dass 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

versuche es hier

http://octave-online.net/

Abr001am
quelle
Weitere Verbesserungen erforderlich
Abr001am
Leute sind hier nicht gewohnt mit Matlab?
15.
0

Python 2, 303 Bytes

Probieren Sie es online aus

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

Die Infix-Ausgabe enthält **statt ^. Wenn dies nicht zulässig ist, .replace('**','^')werden weitere 18 Byte hinzugefügt

Erläuterung:

# 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
Totes Opossum
quelle