見つけるためのプログラム書く1から9までの数字のそれぞれが一度だけ表示される9桁からなる番号を。この数は、これらの分割可能要件も満たしている必要があります。
- 数は9で割り切れる必要があります。
- 右端の数字を削除すると、残りの数字は8で割り切れます。
- 新しい番号の右端の桁を削除すると、残りの番号は7で割り切れるはずです。
- 以下同様に、1桁になるまで(これは必ず1で割り切れます)。
クレジットDávidNémeth
見つけるためのプログラム書く1から9までの数字のそれぞれが一度だけ表示される9桁からなる番号を。この数は、これらの分割可能要件も満たしている必要があります。
クレジットDávidNémeth
回答:
1{;9,:)_mrs0@{_3$<i\%+}/}g
ランダム化されていますが、Javaインタープリターでかなり高速に動作します。それは取ることができますカップルと分のオンライン通訳を。
説明:
1pushs 1(後で説明します)
{…}gはdo-whileループで
;スタックから値を削除し(最初は1から始めました)
9,、配列[0 ... 8]
:)が配列要素をインクリメントし、[1 ... 9]
_配列複製
mrシャッフル配列の
s文字列に変換する
0@上で、アレイの他のコピーをもたらし、次にプッシュ0
{…}/(番号1 ... 9以上)のために、各ループである
_現在の数(レッツコールその「K」を複製し)
3$スタックから数値文字列をコピー
<iし、最初のk文字の部分文字列を取得してから、k
\%の他のコピーと整数スワップに変換し、残り(%k)を取得して
+、残りをスタックの前の値に追加します(最初は上から0) )
この時点で、スタックには数値文字列があり、数値がすべての要件に一致する場合(つまり、残りがすべて0の場合)は0、それ以外の場合は0以外の値が続きます。
スタックの一番上がdo-whileループ状態になります。ポップされ、条件がtrueの場合はループが続行されます。
解が見つかった場合、条件は0(false)であり、ループは終了し、スタックの残り(数値文字列)が出力されます。
それが解決策でない場合、条件は0以外の値(true)であり、ループはスタック上の文字列で続行されます。文字列は次の反復の開始時にポップされます(そのため、ループはスタック上の値を期待し、それが最初の1の理由です)。
コードをより短く複雑にしてくれたDennisに感謝します:p
0{;9,:)_mrsT@{_3$<i\%+}/}g
数の再帰的構築、各ステップは可分性をチェックします。
ランタイムは0秒近くです。
今回はI / Oがありません。OPがプログラムに番号を見つけるように要求したため、番号が見つかり、自動的にコンソールに記録されました。
MT0の好意でゴルフをした
(Q=(n,d,b)=>([(m=n+(s=[...b]).splice(i,1))%d||Q(m,d+1,s)for(i in b)],d>9&&(Q.z=n),Q.z))('',1,'123456789')
ゴルフ
(Q=(n='',d=1,b=[...'123456789'],i)=>{
for(i=0;s=[...b],m=n+s.splice(i,1),b[i];i++)m%d||Q(m,d+1,s);d>9&&(Q.z=n);return Q.z;
})()
醜い
(Q=(n='', d=1, b=[...'123456789'], i) => {
for(i=0; s=[...b], m=n+s.splice(i,1), b[i]; i++)
m % d || Q(m,d+1,s);
d > 9 && (Q.z=n);
return Q.z;
})()
ボーナス
3つの小さな変更で、同じ関数を使用して、base> 10を使用してより長い数を見つけることができます。たとえば、base 14で...
(Q=(n='',d=1,b=[...'123456789ABCD'],i)=>{
for(i=0; s=[...b], m = n+s.splice(i,1), b[i]; i++)
parseInt(m,14)%d || Q(m,d+1,s);
d>13 && (Q.z=n);
return Q.z;
})()
9C3A5476B812D
未ゴルフ
Q=(n,d,b,i,c,z)=>{ // i,c,z fake parameters instead of vars.
for (i=0; b[i]; i++)
{
s=[...b];
m = n + s.splice(i,1);
if (m % d == 0)
if (z = d<9 ? Q(m, d+1, s) : m) return z;
}
}
Q('',1,[...'123456789'])
(Q=(n,d,b)=>([(m=n+(s=[...b]).splice(i,1))%d||Q(m,d+1,s)for(i in b)],d>9&&(Q.z=n),Q.z))('',1,'123456789')
(Q=(n,d,b)=>Math.max(...[(m=n+(s=[...b]).splice(i,1))%d||Q(m,d+1,s)for(i in b)],n))('',1,'123456789')
使用法: perl -E '...'
{$s++;redo if grep{$s!~$_||substr($s,0,$_)%$_}1..9}say$s
出力: 381654729
このプログラムは本当に遅いです。3.5時間以上のように。
より楽しい演習として、私は非常に高速なアルゴリズムを開発することにしました。
my $set = [1..9];
for my $divisor (2..9) {
my $newset = [];
for my $element (@$set) {
my $num = $element * 10;
for (my $digit = $divisor - ($num % $divisor); $digit < 10; $digit += $divisor) {
if (index($element, $digit) == -1) {
push @$newset, $num + $digit;
}
}
}
$set = $newset;
}
print "@$set\n";
上記は.00095秒で実行され、この問題の解決策が1つしかないことを確認します。
from itertools import*
g=lambda i,d:d==1!=print(i)or int(i[9:])%d==0!=g(i[:-1],d-1)
for x in permutations("123456789"):g("".join(map(str,x))*2,9)
出力:
381654729
これは私の最初のゴルフ台本です。あなたはそれが好きだと思います:)
=Y]kFkY~Yf>ql{TlT%vTlTm+k`dr1T)pk
これをテストするには、上記のコードを標準入力としてタイトルのリンクに挿入します。
Python 3.4にコンパイルした後:
k=''
T=10
Y=[k]
for k in Y:
Y+=list(filter(lambda T:(len(set(T))==len(T))>(eval(T)%len(T)),
map(lambda d:k+repr(d),range(1,T))))
print(k)
説明:
=Y]k:Y=['']
FkY:Fのkの場合:
~Y:Yに追加
f:フィルター
>ql{TlT:すべてのユニークな要素と
%vTlT:eval(要素)%len(要素)= 0
m+k` d
k + repr(d)のリスト
r1T:dは1から9まで。
):ループの終了
pk:プリントk
[*r=1..9].permutation{|i|r.all?{|x|eval(i[0,x]*"")%x<1}&&$><<i*""}
実行時間は約8秒です(出力は3秒後に印刷されます)。
これは最初の数値を見つけた後も止まらないため、技術的には基準を満たすすべての数値を出力しますが、そのような数値は1つしかないため、違いはありません。
[*r=1..9].permutation{|i|r.all?{|x|eval(i[0,x]*"")%x<1}&&$><<i}
基本的に上記と同じソリューション。Ruby 1.8では、配列は暗黙的に呼び出さArray#joinれて文字列に変換されるため、その呼び出しを保存できます。興味深いことに、コードはRuby 1.8でも2.0よりはるかに高速に実行されます(合計実行時間4.5秒、出力は1.6秒後に印刷されます)。
1,{{10*){.)}8*}%{`..&=},{.`,%!},}9*
これにより、条件を満たすプレフィックスが作成されます。
# Initial prefixes: [0]
1,
# Loop 9 times
{
# Extend each prefix by digits 1 to 9
{10*){.)}8*}%
# Filter out ones which repeat a digit
{`..&=},
# Filter down to ones which are divisible by their length
{.`,%!},
}9*
これが私の素人っぽいHaskellの試みです(提案/改善は大歓迎です)。最短ではないかもしれませんが、それだけで実行されます.19 私のシステムでFlonkが変更されてから0.65秒。
import Data.List;f=foldl1$(+).(*10);main=print$[f x|x<-permutations[1..9],f[mod(read.take y.show$f x)y|y<-[9,8..1]]<1]!!0
<!-- language: lang-haskell -->構文を強調表示するために、コードの前に2行追加してください。
foldl1ただし、を関数に分離することにより、sumまたはの代わりにそれを使用できますany。import Data.List;f=foldl1$(+).(*10);main=print$[f x|x<-permutations[1..9],f[mod(read.take y.show$f x)y|y<-[9,8..1]]<1]!!0
fに、mod述語で関数を使用することは絶対に好きです。
!!0への呼び出しで置き換えることもできfます。順序は関係ないため、リスト[9,8..1]はで置き換えることもできxます。コードの再利用について話してください!
ブルートフォースソリューション(超低速)
for(a=c=1;b=c&&++a;)for(c=9;~(a+'').search(c)&&b%c<1;)--c?b=b/10|0:alert(a)
この存続期間の結果を確認する場合は、初期値を次のように更新します a=c=38e7
for(a=1;b=++a;)for(c=9;~(a+'').search(c)&&b%c<1;)--c?b=b/10|0:alert(a)
そして、ただ楽しむために、はるかに速く実行されるランダムな総当たり攻撃(ES6のみ)
for(a=i=[..."123456789"];b=c=i&&a.sort(x=>Math.random()*9-5|0).join('');)for(i=9;c%i<1;)--i?c=c/10|0:alert(b)
私が彼のコードを正しく理解していれば、基本的には@Venteroのソリューションと同じですが、Pythonで行われます(クレジットの多くは@Greg Hewgillに支払われます)。
from itertools import*;print[s for s in map(''.join,permutations('123456789'))if all(t(s[:i])%i==0 for i in range(1,9))][0]
r(9,1,-1)でr(9)繰り返しの順序は本当に重要ではありませんので、。
r(1,9)ので使用する必要%0があります。
r(1, 9)Pythonで使用する必要があります。
permutations("123456789")、''.join(s[:i])おそらくあなたが持っているものよりも短い(そしてあなたは排除することができるr=range)
これで私の刺し傷...
Seq(1,2,3,4,5,6,7,8,9).permutations.filter(p=>(2 to 8)forall{n=>(p.take(n).mkString.toLong%n==0)}).map(_.mkString.toLong).toList
(2 to 8)との間のスペースを削除すると、キャラクターを保存できますforall。
使用法: perl -M5.010 find-9-digits.pl
{$s=join'',sort{4-rand 8}1..9;redo if grep{substr($s,0,$_)%$_}2..9}say$s
出力: 381654729
このプログラムは遅いです。数字「123456789」をシャッフルするため、10秒以上かかる場合がありますが、シャッフルには欠陥があります。
未ゴルフ:
# Enter a block.
{
# Shuffle the characters "123456789".
$s = join('', sort({2 - rand(4)} 1..9));
# Redo block if any divisiblity test fails; grep returns the
# number of failing tests.
redo if grep({
# For each divisor $_ in 2..9, test if the first $_ digits of
# of $s are divisible by $_. The test fails if the remainder
# is a true value (not zero).
substr($s, 0, $_) % $_
} 2..9);
}
say $s;
数字の配列1..9をシャッフルするコードを使用しました。
use List'Util shuffle;shuffle 1..9 (34文字)sort{(-1,1)[rand 2]}1..9 (24文字)sort{.5<=>rand}1..9 (19文字)sort(2-rand 4}1..9 (18文字)sort{4-rand 8}1..9 (18文字)Perlは、ソートブロックが$ aと$ bを一貫した方法で比較することを期待しています。私の並べ替えブロックは$ aと$ bを決して見ません。それらはランダムな順序を返すため、並べ替えはシャッフルになります。
を使用するsort{.5<=>rand}1..9と、プログラムの実行速度が速くなります。これは、0.5と、1.0を除く0.0から1.0までのランダムな浮動小数を比較して、1/2の確率で$ a <$ b、ほぼ1/2の確率で$ a> $ bです。(注意:これは「Microsoftシャッフル」であり、公平なシャッフルではあり.5<=>randません。一貫した順序を提供しないため、これには偏りがあります。)
私が1つのキャラクターを離れてゴルフし、はるかに悪いものを使用するとしますsort(2-rand 4}1..9。Perlは、ソートブロックが整数を返すことを期待します2-rand 4が、浮動小数点です。これは、-2.0を除く-2.0から2.0までのランダムなフロートです。Perlはこの浮動小数点数をゼロに向かって切り捨て、次の結果になります。
$ == $ bの、Perlは十分にシャッフルされません。したがって、私のプログラムは、2-rand 4頻繁に0を返さない十分なシャッフルを取得するまで、より多くのシャッフルを実行します。プログラムの実行速度が非常に遅いため、1分以上かかる場合があります。
私はを使用sort{4-rand 8}1..9しているので、$ a == $ bである確率は1/4 であり、私のプログラムはシャッフルを少なくしています。
0{)_`$A,1>s=!1$9,{9\m1$\%@+\A/}/;}g
約27分後、次の出力が生成されます。
381654729
0 " Push 0 (“n”). ";
{ " ";
)_`$ " Increment “N”, duplicate, stringify and sort the resulting string. ";
A,1>s " Push '123456789'. ";
=! " Push 0 if the strings are equal and 1 otherwise (“a”). ";
1$ " Copy “n”. ";
9,{ " For each i in [ 0 1 2 3 4 5 6 7 8 ]. ";
9\m " Calculate “9 - i”. ";
1$\% " Calculate “n % (9 - i)”. ";
@+ " Add the result to “a”. ";
\A/ " Swap “a” with “n” and calculate “n / 10”. ";
}/ " ";
; " Discard “n”. ";
}g " If “a > 0”, repeat the loop. ";
g([],O,_,O).
g(L,N,I,O):-nth1(_,L,D,R),M is N*10+D,J is I+1,0 is M mod J,g(R,M,J,O).
数字のリストをクエリで指定する必要があるため、これは少し不正です。
?- g([1,2,3,4,5,6,7,8,9],0,0,O).
O = 381654729 ;
false.
しかし、それがこのコードを面白くするものです。数字のリストの問題を解決できます。例えば:
?- g([1,2,3,4,5,6,7,8,9,0],0,0,O).
O = 3816547290 ;
false.
?- g([1,2,3,4,5,6,7,8],0,0,O).
O = 38165472 ;
false.
?- g([1,2,3,4,5,6,7],0,0,O).
false.
?- g([1,2,3,4,5,6],0,0,O).
O = 123654 ;
O = 321654 ;
false.
?- g([2,2,3,3,5,6,7,8,9],0,0,O).
O = 363258729 ;
O = 363258729 ;
O = 363258729 ;
O = 363258729 ;
O = 723258963 ;
O = 723258963 ;
O = 723258963 ;
O = 723258963 ;
false.
l=`echo {1..8}`
for d in {2..8};{
l=$(printf "a=%s;if(!a%%$d)a\n" $(eval echo {${l// /,}}{1..8}|tr \ '
'|grep -Pv '(\d).*\1')|bc|paste -d\ -s -)
}
echo ${l}9
これは少し長いですが、これはおそらく0.1秒未満で実行される(通常は遅い)シェルスクリプトであることを考えると、アルゴリズムはおそらく最も高速なものの1つだと思います。
アルゴリズムは次のようになります。
grep)$dを使用してbc、(桁数)で分割可能かどうかを確認しますprintfいくつかのショートカットがありますが、これらは数学的には正しいと思います:
私はこれをC ++で試さなければなりませんでした。明らかに、それは最短の解決策にはならないでしょうが、ここにそれがあります:
#include <algorithm>
using namespace std;bool c(int n,int d=9){return d<2||n%d==0&c(n/10,d-1);}int main(){for(char n[]="123456789";next_permutation(n,n+9);)if(c(atoi(n)))return atoi(n);}
一部の文字を保存するために出力する代わりに番号を返します(くそー)もちろん、POSIXシステムでは、これは8ビットの符号なしに変換されるため、正しくありません。ただし、プログラムは正しい数を計算します。
Ungolfed(C ++ 11が必要):
#include <iostream>
#include <algorithm>
using namespace std;
bool check(int n, int digit = 9)
{
return (n % digit==0) && (digit == 1 || check(n/10,digit-1));
}
int main()
{
string num {"123456789"};
while (next_permutation(begin(num), end(num)))
if (check(stoi(num))){
cout << num << endl;
break;
}
}
T-sqlは非常に競争の激しいゴルフ言語ではありません...
with A(n)as(select top 10 number from spt_values where'p'=type),R as(select \r,1l union all select r*10+n,l+1from R,A where n not in(select substring(str(r),n,1)from A)and(r*10+n)%l=0)select max(r)FROM R
masterデータベースで実行する必要があります。最初のCTEをこれに置き換えてデータベースに依存しないようにすることができますが、さらにいくつかの文字を使用します(2008が必要です)。
with A as(select*from(VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9))f(n))
読みやすい編成:
with A(n)as(select top 10 number from spt_values where'p'=type),
R as(select \ r,1 l
union all
select r*10+n,l+1
from R,A
where n not in (
select substring(str(r),n,1)
from A
)
and(r*10+n)%l=0)
select max(r) FROM R
基本的rに、文字列でまだ表示されていない数字の後ろに数字を追加し続け、新しい文字列が現在のレベルのモジュロ0であることを確認します。Rをに初期化し\ます。これが実際にこのコードの唯一のトリックです。これは、moneyデータ型で0に設定するためのクレイジーな方法です。\通貨の代わりにタイプさせる方法を私は推測しています。 $T-SQLでも同じことを行いますが、$l存在しない疑似列を解釈しようとしてエラーをスローします。これにより、使用に関する心配を回避できますintこれにより、通常は10番目の連結でオーバーフローが発生し、実際にレベルをチェックする必要があります。編集:おもしろい事実2014年のT-sqlには、文字列を値のテーブルに変換する組み込みの方法がない(たとえば、split funcがない)ので、実際にAテーブルを2回再利用して、ストリング化されたR
T-Sql優先ルールは煩わしいので、文字列連結ではなく数値連結(* 10 + n)を使用する必要があります。
with A as(select 1n union all select n+1 from A where n<9),
for($n=123456789;$n=str_shuffle($n);$d||die("$n"))for($d=10;--$d&&substr($n,0,$d)%$d<1;);
数字を含む文字列をシャッフルし、ループ内で可分性をテストします。
で実行し-nrます。
for(;++$i<1e9;$d||die("$i"))for($d=10;--$d&&max(count_chars($i))<2&substr($i,0,$d)%$d<1;);
100000001からループし、内部ループの分割可能性をテストし、解が見つかると終了します。
function f($n="",$e=1){while($d++<9)strpos(_.$n,"$d")|($x=$n.$d)%$e||print$e>8?$x:f($x,$e+1);}
数値にまだ含まれていない1桁を追加します。長さによる分割が可能であれば、再帰(または出力)します。
これは、解決策が1つしかないことを利用しています。それがprint$e>8?$x:f($x,$e+1)なければ、print$e>8?"$x\n":f($x,$e+1)(+ 3バイト、すべてのソリューションを出力する)または($e>8?die("$x"):f($x,$e+1))(+4バイト、最初のソリューションで終了する)でなければならず、そうでない場合、ソリューションは区切り文字なしで出力されます。
と電話する f();
-
ブルートフォースバージョンには明らかな理由でTiOがありませんが、他の2つを試すことができます。
関数呼び出しのランタイムはインラインで測定されます(2〜4ミリ秒の間)。
合計実行時間はWebサイトによって測定されます(通常は50〜500ミリ秒)。