非常に素晴らしいフリードマン番号


13

A フリードマン数は、*、/、^、括弧と連結-操作+、と組み合わせて独自の数字を使用して非自明な式に等しい正の整数です。

ニース・フリードマン数は、自明な式に等しい正の整数であり、元の順序で数字を使用して、同じ操作と組み合わせて独自の数字を使用します。

私がここで発明している非常に素晴らしいフリードマン数(VNFN)は、そのような表現のあまりきれいでない(私の意見では)部分なしで書くことができるニース・フリードマン数です。括弧、連結、および単項否定は許可されていません。

この挑戦のために、括弧なしで式を書く3つの可能な方法があります。

プレフィックス:これは左結合性と同等です。このタイプの式は、すべての演算子が数字の左側に記載されています。各演算子は、次の2つの式に適用されます。例えば:

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

この方法で記述できるVNFNは343です。

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

後置:これは、右結合性と同等です。操作は数字の右側に移動することを除いて、プレフィックス表記に似ています。各演算子は、前の2つの式に適用されます。例えば:

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

この方法で記述できるVNFNは15655です。

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

中置:中置表記法では、5つの操作に標準の操作順序が使用されます。チャレンジのために、その操作の順序は次のように定義されます^。次に、括弧で囲み*/同時に連想的に残します。最後に、括弧で囲む+-同時に、連想的に残します。

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は11664です。

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

課題:正の整数が与えられ、それが接頭辞、中置または後置記法のいずれかでそれ自身の数字の自明でない表現として表現できる場合、その表現を出力します。そうでない場合は、何も出力しません。

明確化:複数の表現が可能な場合、それらの空でないサブセットを出力できます。たとえば、736はVNFNです。

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

+^7367+3^6またはその両方が出力として受け入れられます。

「Trivial」式とは、演算子を使用しない式を意味します。これは1桁の数字にのみ関係し、1桁の数字はVNFNにはなり得ないことを意味します。これは、フリードマン数の定義から継承されます。

100万未満の入力では、回答は数秒または数分で実行されます。

関連。

IO:標準IOルール。完全なプログラム、機能、動詞など。STDIN、コマンドライン、関数の引数など。「Nothing」を出力するには、空の文字列、空行などnull、および空のコレクションで十分です。出力は、表現に含めることができない文字で区切られた文字列、または文字列のコレクションです。

例:

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

得点:これはコードゴルフです。少ないバイトが勝ちます。

また、見つかった場合は、回答に新しいVery Nice Friedman Numberを入力してください。


*(+(*(1,2),3,4)後に、1つのに近い括弧が欠落している,3
SPARR

「数秒または数分」の上限は何ですか?4時間はまだ....多く...分です。
チャールズではない

@NotthatCharles 4時間は長すぎます。私のマシンで1時間、部屋を少し揺らしてみましょう。複数桁の数字について、それは私が連結によって言及していたことですParentheses, concatenation and unary negation are disallowed.
-isaacg

回答:


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

で呼び出す perl -M5.10.0 scratch.pl 736


結果

私が見つけた最初のいくつかの結果は次のとおりです。

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

説明

完全に無制限

後のゴルフを楽にするために、できるだけ自分自身を繰り返すようにしました。

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

ゴルフの仕方

  • 空白とコメントを削除し、すべての変数を1文字バージョンに置き換えます
  • プログラムをラップする $_=q! ... !;eval
  • 文字列を抽出し、後で置換します。

これにより、次のような結果が得られ、そこから結果の改行を削除できます。

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

答えてくれてありがとう、そして最初の場所にいることをおめでとう。広範なストライキでは、どのように機能しますか?
isaacg

私はperlを知りませんが、3つの出現を抽出し、}globいくつかのバイトを保存できる可能性があるようです。
isaacg

s!B!}glob!g;BBB-> 15B; }glob}glob}glob-> 15B :)
アレクサンダーブレット

くそー、とても近い。
isaacg

4

Rubyの2.1.5のみ- 213 220 238 + 9 = 247

RubyがPerlをどのように打ち負かすかはわかりませんが、ここに行きます...

-rtimeoutフラグ(および-W0またはstderrを他の場所に送信)を使用してこれを実行します。

これをわずかに堅牢にするために、余分な文字(つまり248)に置き換えsend([].methods[81],z-1)repeated_permutation(z-1)スコアを付けます。

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

基本的に、演算子のすべての順列を調べて、中置、後置、および接頭辞をこの順序で試してください。このdメソッドはeval2番目のパラメーターを使用して計算を実行し、DivideByZeroまたはOverflow例外をキャッチします。

ただし、stderrを/ dev / nullに送信する必要evalがあります(eval):1: warning: in a**b, b may be too big。そうしないと、のような警告が出力される場合があります。

このアンゴルフを思いついたときに、3匹のイワナを救う方法を見つけました!

Ungolfed(時代遅れだが似たような原則):

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

変更履歴

247は、タイムアウトする代わりに、より大きな数に対してこの作業を行いました。

220は、括弧配列を宣言することで3つの文字を削り取り、1桁の数字がVNFNと見なされるバグを修正しました

213初期コミット


素晴らしい解決策-私にとって完全な黒魔術!Rubyにはzipおよび置換関数が組み込まれているため、RubyはPerlに勝っていると思います。
アレクサンダーブレット

@ alexander-brettの方がいいですか? a.zip(b,c)様配列の配列を返す[ [a[0],b[0],c[0]],[a[1],b[1],c[1]], etc.]['hi', 'there']*''ちょうど配列値の文字列表現を連結します。
チャールズではない

ああ、そして[a,b]*3降伏[a,b,a,b,a,b]
チャールズではない

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

ここで試してみてください

http://octave-online.net/


さらに改善が必要
Abr001am

人々はここでMATLABに慣れていませんか?
-Abr001am

0

Python 2、303バイト

オンラインで試す

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

中置出力にはの**代わりにが含まれます^。これが許可されていない場合、.replace('**','^')発生し、さらに18バイトを追加します

説明:

# 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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.