Angka Friedman yang sangat bagus

13

Angka Friedman adalah bilangan bulat positif yang sama dengan ekspresi non-sepele yang menggunakan digit sendiri dalam kombinasi dengan operasi +, -, *, /, ^, tanda kurung dan gabungan.

Angka Nice Friedman adalah bilangan bulat positif yang sama dengan ekspresi non-sepele yang menggunakan digit sendiri dalam kombinasi dengan operasi yang sama, dengan digit dalam urutan aslinya.

Angka Friedman yang sangat bagus (VNFN), yang saya temukan di sini, adalah angka Friedman yang bagus yang dapat ditulis tanpa bagian ekspresi yang kurang cantik (menurut saya). Kurung, konkatasi, dan negasi unary tidak diizinkan.

Untuk tantangan ini, ada tiga kemungkinan cara menulis ekspresi tanpa tanda kurung.

Awalan: Ini sama dengan asosiasi kiri. Jenis ekspresi ini ditulis dengan semua operator di sebelah kiri digit. Setiap operator berlaku untuk dua ekspresi berikut. Contohnya:

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

VNFN yang dapat ditulis dengan cara ini adalah 343:

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

Postfix: Ini setara dengan asosiasi kanan. Ini seperti notasi awalan, kecuali bahwa operasi pergi ke kanan digit. Setiap operator berlaku untuk dua ekspresi sebelumnya. Contohnya:

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

VNFN yang dapat ditulis dengan cara ini adalah 15655:

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

Infix: Notasi infix menggunakan urutan operasi standar untuk lima operasi. Untuk keperluan tantangan, urutan operasi itu akan didefinisikan sebagai berikut: Memberhentikan ^terlebih dahulu, benar secara asosiatif. Kemudian, kurung *dan /secara bersamaan, pergi secara asosiatif. Akhirnya, kurung +dan -secara bersamaan, pergi secara asosiatif.

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 yang dapat ditulis dengan cara ini adalah 11664:

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

Tantangan: Diberikan bilangan bulat positif, jika dapat dinyatakan sebagai ekspresi non-sepele dari digitnya sendiri baik dalam notasi awalan, infiks atau postfix, output ekspresi itu. Jika tidak, tidak menghasilkan apa-apa.

Klarifikasi: Jika beberapa representasi dimungkinkan, Anda dapat menampilkan subset yang tidak kosong. Misalnya, 736 adalah VNFN:

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

+^736, 7+3^6atau keduanya akan menjadi keluaran yang dapat diterima.

Ekspresi "Trivial" berarti ekspresi yang tidak menggunakan operator apa pun. Ini hanya relevan untuk satu angka angka, dan berarti bahwa satu angka angka tidak boleh VNFNs. Ini diwarisi dari definisi Nomor Friedman.

Jawaban harus berjalan dalam hitungan detik atau menit pada input di bawah satu juta.

Terkait

IO: Aturan IO standar. Program penuh, fungsi, kata kerja atau sejenisnya. STDIN, baris perintah, argumen fungsi atau yang serupa. Untuk menghasilkan "Tidak Ada", string kosong, baris kosong, nullatau serupa, dan koleksi kosong semuanya baik-baik saja. Keluaran dapat berupa string yang dibatasi dengan karakter yang tidak bisa dalam representasi, atau mungkin kumpulan string.

Contoh:

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

Penilaian: Ini adalah kode golf. Bytes paling sedikit menang.

Juga, jika Anda menemukannya, tolong berikan Nomor Friedman Sangat Bagus baru dalam jawaban Anda.

isaacg
sumber
*(+(*(1,2),3,4)hilang satu paren dekat, setelah,3
Sparr
Apa tutup "dalam detik atau menit"? Empat jam masih dalam .... banyak ... menit.
Bukan karena Charles
@NotthatCharles 4 jam terlalu banyak. Katakanlah 1 jam di mesin saya, dengan ruang gerak. Tentang angka multi-digit, itulah yang saya Parentheses, concatenation and unary negation are disallowed.
maksudkan

Jawaban:

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

Telepon dengan perl -M5.10.0 scratch.pl 736


Hasil

Beberapa hasil pertama yang saya temukan adalah:

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

Penjelasan

Sepenuhnya ungolfed

Saya berusaha mengulangi diri saya sebanyak mungkin untuk membuat golf nanti lebih mudah.

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

Bagaimana cara bermain golf

  • Hapus spasi & komentar dan ganti semua vars dengan versi 1 karakter
  • Bungkus program dalam $_=q! ... !;eval
  • Ekstrak string dan gantilah setelahnya.

Ini memberikan sesuatu seperti ini, dari mana Anda dapat menghapus jeda baris untuk hasilnya:

$_='
    $_=$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
sumber
Terima kasih atas jawabannya, dan selamat karena berada di tempat pertama. Dalam pemogokan luas, bagaimana cara kerjanya?
isaacg
Saya tidak tahu perl, tetapi sepertinya dimungkinkan untuk mengekstrak 3 kejadian }globdan menyimpan beberapa byte.
isaacg
s!B!}glob!g;BBB-> 15B; }glob}glob}glob-> 15B :)
alexander-brett
Sial, sangat dekat.
isaacg
4

Hanya Ruby 2.1.5 - 213 220 238 + 9 = 247

Tidak yakin bagaimana Ruby mengalahkan Perl, tapi ini dia ...

Jalankan ini dengan flag -rtimeout (dan -W0 atau kirim stderr Anda ke tempat lain).

Untuk membuat ini sedikit lebih kuat, ganti send([].methods[81],z-1)dengan repeated_permutation(z-1)dan nilai karakter tambahan (jadi, 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)]}

Pada dasarnya, telusuri semua permutasi operator dan coba infiks, postfix, dan prefix dalam urutan itu. The dmetode penggunaan evalpada parameter kedua untuk melakukan perhitungan, menangkap setiap DivideByZero atau Overflow pengecualian.

Anda perlu mengirim stderr ke / dev / null, atau yang lain evalakan mencetak peringatan seperti (eval):1: warning: in a**b, b may be too big.

Sementara saya menemukan ungolfing ini, saya menemukan cara untuk menyelamatkan tiga karakter!

Tidak disatukan (prinsip-prinsip usang tetapi serupa):

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 membuat ini berfungsi untuk angka yang lebih besar daripada waktu habis.

220 mencukur tiga karakter dengan mendeklarasikan array paren, dan memperbaiki bug di mana satu digit angka dianggap sebagai VNFN

213 komit awal

Bukan itu Charles
sumber
Solusi hebat - sempurnakan ilmu hitam bagi saya! Saya kira ruby ​​beats Perl karena ia memiliki fungsi zip dan permutasi bawaan.
alexander-brett
@ alexander-brett lebih baik? a.zip(b,c)mengembalikan array array seperti [ [a[0],b[0],c[0]],[a[1],b[1],c[1]], etc.]dan ['hi', 'there']*''hanya merangkai representasi string dari nilai array.
Bukannya Charles
oh, dan [a,b]*3hasilkan[a,b,a,b,a,b]
Bukan berarti 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

coba di sini

http://octave-online.net/

Abr001am
sumber
masih banyak perbaikan yang diperlukan
Abr001am
orang tidak terbiasa dengan matlab di sini?
Abr001am
0

Python 2, 303 byte

Cobalah 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

Output infix akan berisi **bukan ^. Jika ini tidak diizinkan, .replace('**','^')akan muncul dan menambahkan 18 byte lagi

Penjelasan:

# 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
Possum Mati
sumber