Bardzo ładne liczby Friedmana

13

Friedman ilość jest dodatnią liczbą całkowitą, która jest równa nietrywialną ekspresji, który wykorzystuje własne cyfry w połączeniu z operacjami +, -, * / ^ w nawias i konkatenacji.

Liczba Nicea Friedmana jest dodatnią liczbą całkowitą równą nietrywialnemu wyrażeniu, która używa własnych cyfr w połączeniu z tymi samymi operacjami, z cyframi w ich oryginalnej kolejności.

Bardzo ładny numer Friedmana (VNFN), który tutaj wymyślam, to ładny numer Friedmana, który można zapisać bez mniej ładnych (moim zdaniem) części takiego wyrażenia. Nawiasy, konkatenacja i jednoargumentacja są niedozwolone.

W przypadku tego wyzwania istnieją trzy możliwe sposoby napisania wyrażenia bez nawiasów.

Prefiks: Jest to równoważne lewostronnemu skojarzeniu. Ten typ wyrażenia jest zapisywany wszystkimi operatorami po lewej stronie cyfr. Każdy operator stosuje się do następujących dwóch wyrażeń. Na przykład:

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

VNFN, który można zapisać w ten sposób, to 343:

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

Postfiks: Jest to równoważne z prawym skojarzeniem. To jest tak jak zapis przedrostka, z tą różnicą, że operacja przebiega po prawej stronie cyfr. Każdy operator stosuje się do dwóch poprzednich wyrażeń. Na przykład:

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

VNFN, który można zapisać w ten sposób, to 15655:

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

Infix: Notacja Infix używa standardowej kolejności operacji dla pięciu operacji. Na potrzeby wyzwania kolejność operacji zostanie zdefiniowana w następujący sposób: ^Najpierw nawiasuj , a następnie skojarz . Następnie nawiasuj *i /jednocześnie odejdź asocjacyjnie. Wreszcie nawiasuj +i -jednocześnie odejdź asocjacyjnie.

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

VNFN, który można zapisać w ten sposób, to 11664:

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

Wyzwanie: Biorąc pod uwagę dodatnią liczbę całkowitą, jeśli można ją wyrazić jako nietrywialne wyrażenie własnych cyfr w notacji przedrostka, infiksu lub postfiksu, wypisz to wyrażenie. Jeśli nie, nie wysyłaj nic.

Wyjaśnienia: Jeśli możliwe są wielokrotne reprezentacje, możesz wyprowadzić dowolny niepusty ich podzbiór. Na przykład 736 to VNFN:

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

+^736, 7+3^6Albo w obu przypadkach wszystkie są dopuszczalne wyjścia.

Wyrażenie „trywialne” oznacza takie, które nie korzysta z żadnych operatorów. Dotyczy to tylko cyfr jednocyfrowych i oznacza, że ​​cyfry jednocyfrowe nie mogą być numerami VNFN. Jest to odziedziczone po definicji liczby Friedmana.

Odpowiedzi powinny zacząć się w ciągu kilku sekund lub minut na danych wejściowych poniżej miliona.

Związane z.

IO: Standardowe zasady IO. Pełny program, funkcja, czasownik lub podobne. STDIN, wiersz poleceń, argument funkcji lub podobny. Do wyprowadzania „Nic”, pusty ciąg, pusta linia nulllub temu podobne, i pusta kolekcja są w porządku. Dane wyjściowe mogą być ciągiem ograniczonym znakiem, który nie może być w reprezentacji, lub może być zbiorem ciągów.

Przykłady:

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

Punktacja: To jest golf golfowy. Wygrywa najmniej bajtów.

Ponadto, jeśli znajdziesz, podaj w odpowiedzi nowy numer Very Nice Friedman.

isaacg
źródło
*(+(*(1,2),3,4)brakuje jednego bliskiego miąższu, po,3
Sparr
Jaki jest limit „w kilka sekund lub minut”? Jeszcze cztery godziny… za wiele… minut.
Nie, że Charles
@NotthatCharles 4 godziny to za dużo. Powiedzmy, że 1 godzina na mojej maszynie, z jakimś pokojem wiggle. O liczbach wielocyfrowych, o tym właśnie mówiłem, Parentheses, concatenation and unary negation are disallowed.
łącząc

Odpowiedzi:

5

Perl, 345 334 318 293 263 245 B

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

Zadzwoń z perl -M5.10.0 scratch.pl 736


Wyniki

Pierwsze kilka wyników, które znalazłem, to:

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

Wyjaśnienie

Całkowicie nie golfisty

Starałem się powtarzać jak najwięcej, aby ułatwić późniejszą grę w golfa.

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

Jak to gra w golfa

  • Usuń białe znaki i komentarze i zastąp wszystkie zmienne wersją 1-znakową
  • Zawiń program w $_=q! ... !;eval
  • Wyodrębnij ciągi i zastąp je później.

Daje to coś takiego, z którego można usunąć podział linii dla wyniku:

$_='
    $_=$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
źródło
Dzięki za odpowiedź i gratuluję bycia na pierwszym miejscu. W strajkach szerokich jak to działa?
isaacg
Nie znam Perla, ale wygląda na to, że można wyodrębnić 3 wystąpienia }globi zapisać niektóre bajty.
isaacg
s!B!}glob!g;BBB-> 15B; }glob}glob}glob-> 15B :)
Alexander-Brett
Cholera, tak blisko.
isaacg
4

Tylko Ruby 2.1.5 - 213 220 238 + 9 = 247

Nie jestem pewien, jak Ruby pokonuje Perla, ale proszę bardzo ...

Uruchom to z flagą -rtimeout (i albo -W0, albo wyślij swój stderr gdzie indziej).

Aby to nieco bardziej wytrzymałe, wymienić send([].methods[81],z-1)z repeated_permutation(z-1)i zdobyć dodatkową postać (tak, 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)]}

Zasadniczo, przejrzyj wszystkie permutacje operatorów i wypróbuj infix, postfix i prefiks w tej kolejności. W dmetodzie wykorzystuje evalsię do drugiego parametru do wykonywania obliczeń, chwytając żadnych wyjątków DivideByZero lub przelewowy.

Musisz jednak wysłać stderr do / dev / null, w przeciwnym razie evalczasami wydrukuje ostrzeżenia, takie jak (eval):1: warning: in a**b, b may be too big.

Podczas gdy wymyśliłem takie niepoznanie, znalazłem sposób na uratowanie trzech postaci!

Niegolfowane (nieaktualne, ale podobne zasady):

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

Dziennik zmian

247 sprawiło, że działało to w przypadku większych liczb zamiast przekroczenia limitu czasu.

220 zgolił trzy znaki, zadeklarując tablice paren, i naprawił błąd, w którym liczby jednocyfrowe były uważane za VNFN

213 początkowe zatwierdzenie

Nie ten Charles
źródło
Świetne rozwiązanie - kompletna czarna magia dla mnie! Myślę, że Ruby bije Perla, ponieważ ma wbudowane funkcje zip i permutacji.
Alexander-Brett
@ Alexander-Brett jest jeszcze lepszy? a.zip(b,c)zwraca tablicę tablic jak [ [a[0],b[0],c[0]],[a[1],b[1],c[1]], etc.]i ['hi', 'there']*''po prostu łączy reprezentację ciągu wartości tablic.
Nie, że Charles
och, i [a,b]*3daje[a,b,a,b,a,b]
Nie, że 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

spróbuj tutaj

http://octave-online.net/

Abr001am
źródło
potrzeba jeszcze więcej ulepszeń
Abr001am
ludzie nie są tutaj przyzwyczajeni do Matlaba?
Abr001am,
0

Python 2, 303 bajty

Wypróbuj 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

Wyjście Infix będzie zawierać **zamiast ^. Jeśli nie jest to dozwolone, .replace('**','^')wystąpi i doda kolejne 18 bajtów

Wyjaśnienie:

# 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
Dead Possum
źródło