毎月お題を出して、それをいかにエレガントに
プログラミングするかを競うスレ。
言語は自由。お題で指定されている場合はその言語で。
優勝は2chねらーによる投票で行う。
最初のお題:
「エレガントプログラミング投票CGIを作成せよ。」
要求される仕様:
・名前が一覧表示され、「ソース」ボタンを押すと各人が書いたソースコードが表示される。
・名前の横には投票用ラジオボタンがあり、それにチェックを入れる。
・「結果」ボタンを押すと、現時点での投票結果が表示される。
それじゃ、がんばれ。
CGIならWebProg板向けだぞ
************ 仕切り直し ************
例のアレはどうなった?
「人物の顔の画像を与えたとき、チョビヒゲを描いて出力するプログラム」
5 :
デフォルトの名無しさん:01/12/25 21:11
6 :
デフォルトの名無しさん:01/12/25 21:29
「エレガントプログラミング投票CGIをCで作成せよ。」
というわけでperlは禁止。
いつまでかったりーことやってんだよ。バカか?
「エレガントプログラミング投票CGIをプログラムを書かずに実現せよ。」
というわけでコーディング禁止。
拾ってくればいい。
終了
じゃあ別のお題を。
「数列予想プログラムを作成せよ」
初項から第8項までを入力すると、9〜20項目までを表示してくれるもの。
等差数列、等比数列、6次の階差数列(定義は以下に記述)まで対応させること。
つまり、以下のような数列に対応していること。
a) 1 2 3 4 5 6 7 ...
b) 1 2 4 8 16 32 ...
c) 1 2 4 7 11 16 22 ...
d) 1 2 4 8 15 26 42 64 ...
d は、それぞれの項の差が階差数列になっている。
d のようなものを 2 次の階差数列と呼ぶことにする。
c は1次の階差数列である。
言語制限はなし。では、どうぞ。
(追加)
数列として解釈できない場合は、その旨を表示すること。
階比数列(?)にも対応すること。
※階比数列
一般項 A[n] = 初項 * (n ^ 定数) で表わす。
=========================
=========================
========== 糸冬了 ==========
=========================
=========================
==== 長い間ありがとうございました =====
=========================
=========================
まあまってよ。
そこまでうざがること無いじゃないのよ。
宿題じゃねっつーの
なんなら俺が作ったの公開するよ
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
TTypeOfSuuretu = (tsNone, tsKaisa, tsTouhi );
const
Buf = 6;
Count = 20;
var
Data:array [0..Buf-1, 0..Count-1] of Integer;
{ Data[0][0]〜Data[0][Buf-1] が等差・階差数列ならば True }
function IsKaisa:Boolean;
var
AllSame:Boolean;
Depth,i,j: Integer;
begin
{ 余計な部分をクリア }
for i:=1 to Buf-1 do
for j:=0 to Count-1 do
Data[i,j] := 0;
Depth := 1;
repeat
{ 項と項の差 (a[i+1]-a[i]) を取る }
for i:=0 to Buf-Depth-1 do
Data[ Depth, i ] := Data[ Depth-1 ][i+1] - Data[ Depth-1 ][i];
{ 全てが同じ数値かどうか }
AllSame := True;
for i:=0 to Buf-Depth-1 do
if Data[ Depth, i ] <> Data[ Depth, 0 ] then
begin
AllSame := False;
Break;
end;
{ バッファ-2 を越えるか、全てが同じになるまで繰り返す }
Inc( Depth );
until AllSame or (Depth >= Buf-2);
result := AllSame;
end;
{ Data[0][0]〜Data[0][Buf-1] が等比数列ならば True }
function IsTouhi:Boolean;
var
AllSame:Boolean;
Depth,i,j: Integer;
begin
{ 余計な部分をクリア }
for i:=1 to Buf-1 do
for j:=0 to Count-1 do
Data[i,j] := 0;
Depth := 1;
repeat
{ 項と項の商 (a[i+1] / a[i]) を取る }
for i:=0 to Buf-Depth-1 do
begin
if Data[ Depth-1,i ] = 0 then
begin
Result := False;
Exit
end;
Data[ Depth, i ] := Data[ Depth-1, i+1 ] div Data[ Depth-1, i ];
end;
{ 全てが同じ数値かどうか }
AllSame := True;
for i:=0 to Buf-Depth-1 do
if Data[ Depth, i ] <> Data[ Depth, 0 ] then
begin
AllSame := False;
Break;
end;
{ バッファを越えるか、全てが同じになるまで繰り返す }
Inc( Depth );
until AllSame or (Depth >= Buf);
result := AllSame;
end;
procedure CalcKaisa;
var
Depth,i: Integer;
begin
for Depth := Buf-1 downto 1 do
for i := 1 to Count-1 do
Data[ Depth-1, i ] := Data[ Depth-1, i-1 ] + Data[ Depth, i-1 ];
end;
procedure CalcTouhi;
var
Depth,i: Integer;
begin
for Depth := Buf-1 downto 1 do
for i := 1 to Count-1 do
Data[ Depth-1, i ] := Data[ Depth-1, i-1 ] * Data[ Depth, i-1 ];
end;
{ 判定し、後に続く数字を予想する }
{ 判定に成功すれば、数列が Data[0][0]〜Data[0][Count-1] に格納される }
function Hantei: TTypeOfSuuretu;
begin
{ 等差・階差数列かどうか }
if IsKaisa then
begin
CalcKaisa;
Result := tsKaisa;
Exit;
end;
{ 等比数列かどうか }
if IsTouhi then
begin
CalcTouhi;
Result := tsTouhi;
Exit;
end;
Result := tsNone;
end;
var
TypeOfSuuretu: TTypeOfSuuretu;
i,j: Integer;
begin
{ ゼロクリア }
for i:=0 to Buf-1 do
for j:=0 to Count-1 do
Data[i,j] := 0;
{ 値を入力させる }
WriteLn( '最初の ', Buf, ' 項を入力することで、第 ', Count ,' 項までを予測します。');
for i:=0 to Buf-1 do
begin
Write( '第 ' , i+1, ' 項 = ');
ReadLn( Data[0][i] );
end;
{
//DATA 配列表示
for i:=Buf-1 downto 0 do
begin
for j:=0 to Count-1 do
Write(Data[i,j] );
Writeln;
end;
}
{ 判定に成功したならば表示する }
TypeOfSuuretu := Hantei;
case TypeOfSuuretu of
tsKaisa: WriteLn('[ 等差・階差数列 ]');
tsTouhi: WriteLn('[ 等比数列 ]');
tsNone: WriteLn('[ 解析不能 ]');
end;
{ 解析不能でなければ予測結果を表示する }
if TypeOfSuuretu <> tsNone then
begin
for i:=0 to Count-1 do
Write( Data[0][i], ' ' );
WriteLn;
end;
{ 終了 }
WriteLn('終了するには 何かキーを押してください');
ReadLn;
end.
どうでもいいけど長すぎると思います。
よくできました。
========== 糸冬了 ==========
>21
お前も粘着だなおい。
24 :
デフォルトの名無しさん:01/12/26 01:48
Scheme で書きました。階差数列にはまだ対応してません。
(define (stream-car stream)
(car stream))
(define (stream-cdr stream)
(force (cdr stream)))
(define (stream-ref stream n)
(if (= n 0)
(stream-car stream)
(stream-ref (stream-cdr stream) (- n 1))))
(define (tousa? sequence)
(let ((reversed (reverse sequence)))
(cond ((null? reversed) #t)
((= (- (car reversed) 1)
(if (null? (cdr reversed))
(- (car reversed) 1)
(cadr reversed)))
(tousa? (cdr sequence)))
(else #f))))
(define (make-tousa-stream init)
(cons init (delay (make-tousa-stream (+ init 1)))))
(define (touhi? sequence)
(let ((reversed (reverse sequence)))
(cond ((null? reversed) #t)
((= (/ (car reversed) 2)
(if (null? (cdr reversed))
(/ (car reversed) 2)
(cadr reversed)))
(touhi? (cdr sequence)))
(else #f))))
(define (make-touhi-stream init)
(cons init (delay (make-touhi-stream (* init 2)))))
(define (get-stream sequence)
(cond ((tousa? sequence) (make-tousa-stream (car sequence)))
((touhi? sequence) (make-touhi-stream (car sequence)))
(else (error "get-stream: Unknown sequence"))))
;; ここから実行
(display "等差数列のテスト\n")
(define stream (get-stream '(1 2 3 4 5 6 7 8)))
(let loop ((n 8))
(if (< n 19)
(begin (display (stream-ref stream n))
(newline)
(loop (+ n 1)))))
(display "等比数列のテスト\n")
(define stream (get-stream '(1 2 4 8 16 32)))
(let loop ((n 8))
(if (< n 19)
(begin (display (stream-ref stream n))
(newline)
(loop (+ n 1)))))
述語で reverse する必要はありませんね。以下修正版。
長くてすみません。
(define (tousa? sequence)
(cond ((null? sequence) #t)
((= (+ (car sequence) 1)
(if (null? (cdr sequence))
(+ (car sequence) 1)
(cadr sequence)))
(tousa? (cdr sequence)))
(else #f)))
(define (touhi? sequence)
(cond ((null? sequence) #t)
((= (* (car sequence) 2)
(if (null? (cdr sequence))
(* (car sequence) 2)
(cadr sequence)))
(touhi? (cdr sequence)))
(else #f)))
インデントは Emacs でも使ってください。
Schemeわからないけど、これだけで予想プログラムできるの?
ちょっと興味沸いてきたかも(Schemeに)
>>26 できますよ。数列 (リスト) を調べて、対応したストリームを作ってます。
そのストリームから 9〜20 番目の要素を参照しています。
あとは階差に対応させる必要があるんですが、ちょっと面倒。
得点の列を入力して、順位を出力するプログラムをAPLでかけ。
入力例: 85 60 50 90 60
の出力: 2 3 5 1 3
というか、ちっともエレガントじゃない。
30 :
デフォルトの名無しさん:01/12/26 15:46
-- Haskell で書きました。 (
>>9の問題)
diff = interf subtract
same xs = all (== (head xs)) xs
interf :: (a -> a -> b) -> [a] -> [b]
interf f (x1:x2:xs) = f x1 x2 : interf f (x2:xs)
interf _ _ = []
kaisa :: [Integer] -> [Integer]
kaisa xs@(x1:x2:_)
| same $ diff xs = [x1,x2..]
| otherwise = scanl (+) x1 (kaisa (diff xs))
touhi :: [Integer] -> Maybe [Integer]
touhi xs@(x1:x2:_)
| isTouhi xs = Just (iterate (* (x2 `quot` x1)) x1)
| otherwise = Nothing
isTouhi = (\(q,r) -> same q && all (== 0) r) . unzip . interf (flip quotRem)
f :: [Integer] -> [Integer]
f xs | length xs >= 2 = take 20 $ maybe (kaisa xs) id (touhi xs)
| otherwise = []
{- f [1,2,4,8,15] みたいな感じで実行してください。階差にも対応してます。
でも、あまりエレガントじゃないです。ad hoc です。
厳密に作ってないので、入力によっては変なもの吐くかもしれません。許して。 -}
--
>>30 に追加
g = mapM_ print . takeWhile (not . all (== 0)) . iterate diff . f
{-
Main> g [7,-3,4,10]
[7,-3,4,10,-3,-53,-158,-336,-605,-983]
[-10,7,6,-13,-50,-105,-178,-269,-378]
[17,-1,-19,-37,-55,-73,-91,-109]
[-18,-18,-18,-18,-18,-18,-18]
-}
{-
あ、g は階差数列に使うものです。
等比に使うものじゃないです。
Main> g [1,3,9]
[1,3,9,27,81,243,729,2187,6561,19683]
[2,6,18,54,162,486,1458,4374,13122]
[4,12,36,108,324,972,2916,8748]
[8,24,72,216,648,1944,5832]
[16,48,144,432,1296,3888]
[32,96,288,864,2592]
[64,192,576,1728]
[128,384,1152]
[256,768]
[512]
-}
{- bug があった…
> isTouhi = (\(q,r) -> same q && all (== 0) r) . unzip . interf (flip quotRem)
0 で割るだなんて、なんて初歩的な… -}
isTouhi xs = all (/= 0) xs &&
((\(q,r) -> all (== 0) r && same q) $ unzip $ interf (flip quotRem) xs)
>>10 階比数列の定義がよくわからんです。
> 一般項 A[n] = 初項 * (n ^ 定数) で表わす。
で初項が 4 で定数が 3 なら
4,32,108,256,500,864...
みたいになるのですか?
でもそれなら高次の等差数列が扱えれば一緒に扱えそうな感じなんですが。
Main> g [4,32,108,256]
[4,32,108,256,500,864,1372,2048,2916,4000]
[28,76,148,244,364,508,676,868,1084]
[48,72,96,120,144,168,192,216]
[24,24,24,24,24,24,24]
それに階差の定義と比べると整合性がないような…?
>>9の問題をRubyで書いてみた。
階比数列がちと、わからんかったら、それだけ非対応した。
見つからない場合は、例外を投げる。
結構汚い。(鬱
-------------------------------
class Series
def [](i)
unless @nums[i]
@nums << next_int(i-1)
end
return @nums[i]
end
end
class Arithmetical < Series
def initialize(start, skip)
@nums = [start]
@skip = skip
end
def next_int(i)
return self[i] + @skip
end
end
class Difference < Series
def initialize(start, skip_series)
@nums = [start]
@skip_series = skip_series
end
def next_int(i)
return self[i] + @skip_series[i]
end
end
class Geometrical < Series
def initialize(start, power)
@nums = [start]
@power = power
end
def next_int(i)
return self[i] * @power
end
end
---------------------
続く
>>35の続き
--------------------------
class NonMatchSeriesError < RuntimeError; end
class Search
def initialize
@dimesion = 0
end
def match?(arr, series)
match = true
arr.length.times do |i|
unless arr[i] == series[i]
match = false
break
end
end
return match
end
def search_series(a)
if @dimesion == 0 && (a[1] % a[0]) == 0
series = Geometrical.new(a[0], a[1] / a[0])
return series if match?(a, series)
end
series = Arithmetical.new(a[0], a[1] - a[0])
return series if match?(a, series)
if @dimesion > 6
raise NonMatchSeriesError, "でたらめな数列だと思われ"
end
@dimesion += 1
diff = []
(a.length - 1).times do |i|
diff << a[i+1] - a[i]
end
series = Difference.new(a[0], search_series(diff))
return series
end
end
def make_arr(series, i)
a = []
i.times do |x|
a << series[x]
end
return a
end
def solve(a)
s = Search.new
series = s.search_series(a)
if series
re = make_arr(series, 20)
return re[8..19]
end
end
-----------------------
p solve([1,2,3,4,5,6,7,8])
とすると
[9,10,11,12,13,14,15,16,17,18,19,20]
となるはずです。
たぶん、、、
数列の始めに0を渡されるとエラーが出ることに今気づいた。
マジで、鬱だ…
if @dimesion == 0 && (a[1] % a[0]) == 0
を
if @dimesion == 0 && a[0] != 0 && (a[1] % a[0]) == 0
にしてくださいと、、、
>>34 > でもそれなら高次の等差数列が扱えれば一緒に扱えそうな感じなんですが。
高次の階差数列の間違い。
あと、6次って制限を加えなければ
どんな数列も高次の階差数列になるような気がするのだが
どうなんでしょう?
39 :
c,等比数列は実装してないの:01/12/26 21:30
#include <stdio.h>
#include <conio.h>
int main(){
int i,j,tmp,vec[9]={1,0,0,0,0,0,0,0,0},ini[8]={0,0,0,0,0,0,0,0};
for(i=0;i<8;i++){
scanf("%d",&tmp);
for(j=0;j<i;j++)tmp-=ini[j]*vec[j];
ini[i]=tmp;
for(j=i;j>=0;j--)vec[j+1]+=vec[j];
}
if(ini[7])return 1;/* not proper */
for(i=8;i<20;i++){
tmp=0;
for(j=0;j<8;j++)tmp+=ini[j]*vec[j];
printf("%d ",tmp);
for(j=7;j>=0;j--)vec[j+1]+=vec[j];
}
return 0;
}
int main(){
int i,j,tmp,vec[8]={1,0,0,0,0,0,0,0},ini[8]={0,0,0,0,0,0,0,0};
for(i=0;i<8;i++){
for(j=i;j>0;j--)vec[j]+=vec[j-1];
scanf("%d",&tmp);
for(j=0;j<i;j++)tmp-=ini[j]*vec[j];
ini[i]=tmp;
}
if(!tmp){
for(i=8;i<20;i++){
for(j=8;j>0;j--)vec[j]+=vec[j-1];
tmp=0;
for(j=0;j<8;j++)tmp+=ini[j]*vec[j];
printf("%d ",tmp);
}
}else{
if(ini[0]){
tmp=ini[1]/ini[0];
for(i=0;i<7;i++){
if(ini[i]*tmp!=ini[i+1])return 0;
ini[0]*=tmp+1;
}
for(i=8;i<20;i++){
ini[0]*=tmp+1;
printf("%d ",ini[0]);
}
}
}
return 0;
}
>>24-25は問題の意味を理解してなさげ。
>40
結構短く書けるのね。
ちゃんと動いてるようだし。
>>41 そうですか? 階差以外は、40 と同様の動きをしますよ。
ひょっとして入力でしょうか。手続きへの引数って、「入力」ですよね。
手で入力したい場合は (get-stream (read)) でどうぞ。
初項、第2項を入力すると、8項までのリストを作ってくれる関数を引数に取る関数を作って結果を入力と比較するのがエレガント?
44 :
デフォルトの名無しさん:01/12/27 05:29
>42
差が 1、もしくは比が 2 の数列にしか対応してないでしょ?
1 3 5 7 9 11 (差が 2) とか 1 3 9 27 81 (比が 3) のような入力に対しても
それに沿った数列を生成しなきゃいかんのだが。
>43
誰に言ってるの?
40は惜しい。11行目
for(j=8;j>0;j--)vec[j]+=vec[j-1];
↑がj=7ですな。
47 :
デフォルトの名無しさん:01/12/27 09:49
エレガントプログラミングコンテスト
略してエプロン!
エレガントプログラミングコンテスト
略してエロテスト!
49 :
デフォルトの名無しさん:01/12/27 11:57
すんません。「階比数列」というのは我が脳内にのみ
存在する考え方かもしれなかったので、お題修正します。
等差数列
階差数列(高次にも対応)
等比数列
に対応するだけで OK です。「6次の階差」てのもなしにします。
「階差数列(高次にも対応)」ってのは、
「各項の差をとると、それが階差数列になっている」
という数列を指しています。
もちろん、等差数列は階差数列の一種なので。「階差数列」という
表記で統一してもかまわないとは思いますが。
でも、各項同士の差をとり、それを数列として入力に戻してやれば
a[n] = a[n-1] + b[n] (bは等比 or 階差 or 等差数列)
とか、各項同士の商をとり、それを数列として入力に戻してやれば
a[n] = a[n-1] * b[n] (bは等比 or 階差 or 等差数列)
の解析もできそうな気がするのですよ。
ちなみに、階比数列ってのは
a[1] = a[0] * 1
a[2] = a[1] * 2
a[3] = a[2] * 3
a[4] = a[3] * 4
a[n] = a[n-1] * n (n>0において)
とか
a[1] = a[0] * 4
a[2] = a[1] * 6
a[3] = a[2] * 8
a[4] = a[3] * 10
a[n] = a[n-1] * (4 + 2n) (n>0において)
みたいなのを指して言っていました。
>>44 なるほど。ボケてました。
以下修正版。階差数列のストリームを作るのが大変。
(define (stream-car stream)
(car stream))
(define (stream-cdr stream)
(force (cdr stream)))
(define (stream-ref stream n)
(if (= n 0)
(stream-car stream)
(stream-ref (stream-cdr stream) (- n 1))))
(define (tousa-step sequence . step)
(cond ((or (null? sequence)
(null? (cdr sequence))) (car step))
((null? step)
(tousa-step sequence
(- (cadr sequence) (car sequence))))
((= (car sequence)
(- (cadr sequence) (car step)))
(tousa-step (cdr sequence) (car step)))
(else 0)))
(define (tousa? sequence)
(> (tousa-step sequence) 0))
(define (make-tousa-stream init step)
(cons init (delay (make-tousa-stream (+ init step) step))))
(define (touhi-step sequence . step)
(cond ((or (null? sequence)
(null? (cdr sequence))) (car step))
((null? step)
(touhi-step sequence
(/ (cadr sequence) (car sequence))))
((= (car sequence)
(/ (cadr sequence) (car step)))
(touhi-step (cdr sequence) (car step)))
(else 0)))
(define (touhi? sequence)
(> (touhi-step sequence) 0))
(define (make-touhi-stream init step)
(cons init (delay (make-touhi-stream (* init step) step))))
;; 数列を調べてストリームに変換
(define (sequence->stream sequence)
(cond ((tousa? sequence) (make-tousa-stream
(car sequence) (tousa-step sequence)))
((touhi? sequence) (make-touhi-stream
(car sequence) (touhi-step sequence)))
(else (error "sequence->stream: Unknown sequence"))))
51 :
デフォルトの名無しさん:01/12/27 19:41
>>9 なんだっけこれ、ISPだかなんだかの適性検査で使われるよね。
#include <stdio.h>
main(){int i,j,t,v[8],n[8];for(i=0;i<8;i++){v[i]=1;for(j=i-1;j>0;j--)v[j]+=v[j-1
];scanf("%d",&t);for(j=0;j<i;j++)t-=n[j]*v[j];n[i]=t;}if(!t){for(i=8;i<20;i++){
for(j=7;j>0;j--)v[j]+=v[j-1];t=0;for(j=0;j<8;j++)t+=n[j]*v[j];printf("%d ",t);}}
else if(t=n[0]){j=n[1]/t;for(i=0;i<7;i++){if(n[i]*j!=n[i+1])goto e;t*=j+1;}for(i
=8;i<20;i++){t*=j+1;printf("%d ",t);}}else e:printf(":P");}
53 :
デフォルトの名無しさん:01/12/28 02:12
stream って何?
単なる list じゃ駄目なの?
>>50
54 :
デフォルトの名無しさん:01/12/28 02:18
>>53 50じゃないけど、別にlistでもいいと思う。
でも遅延オブジェクトで無限リストとか表現できるから、
この場合streamの方がエレガントなんじゃない?
>>50 > (cons init (delay (make-touhi-stream (* init step) step))))
cons-stream使わないのはなぜ?
>>53 ストリームを使う理由は 54 さんが言う通りです。
お題が「エレガント〜」なので、こっちの方が良いかなと。
>>54 使った方が良いですね。早速マクロ定義してみます。
56 :
デフォルトの名無しさん:01/12/29 12:05
あげ
57 :
デフォルトの名無しさん:01/12/31 17:38
つぎのお題募集
つぎのお題募集
つぎのお題募集
つぎのお題募集
終了
59 :
デフォルトの名無しさん:01/12/31 18:07
計算機。対応する演算子は ()+-*/
ただし、関数定義をできるようにしておくこと。例えば、
f(x)=x*x
f(2+4)
と入力すると、36という解を得る。以下入力例。
3+4 (解は 7)
3+4*2 (解は 11)
14/(3+4) (解は 2)
f(x) = x+2
f(3)(解は 5)
g(x) = x+2
2+g(3)(解は 7)
f(x) = x*2
g(x) = f(x)+2
f( g(3) )(解は16)
言語は自由。では、どうぞ。
60 :
デフォルトの名無しさん:02/01/01 09:16
麻雀:
役は考えない。あがり判定と譜計算のみ。
ロン上がりとツモ上がり、親と子の場合についてイーハンの場合の点数を出す。
62 :
デフォルトの名無しさん:02/01/01 18:27
64 :
デフォルトの名無しさん:02/01/01 19:05
車輪の再発明
Python。エレガントかはしらない。
import string
while 1:
line = raw_input()
if '=' in line:
l = string.split(line, '=')
if len(l) != 2:
print "error"
continue
try: exec("def %s: return %s" % (l[0], l[1]))
except: print "error"
else:
try: print eval(line)
except: print "error"
>65
Pythonを選んだのがエレガント
このスレイイ!
68 :
デフォルトの名無しさん:02/01/02 03:37
>>59の題みておもったんだけど
構文解析するプログラムって
演算子の優先順位ごとに関数つくって再帰するようなアルゴリズムつかうと
どの関数も似たようなのになって何となくイヤな感じがするんですけど
(っていうかだからyaccとかが作られたんだなと思うんだけど
似たような関数つくりまくらないでよくてしかもスタック食いまくらないアルゴリズムっていいのないかな・・
eval使ってエレガントもなにも無いと思うが…
>68 でも、それぞれ加算や掛算や別の事するんだし
71 :
デフォルトの名無しさん:02/01/02 13:11
良スレは200レス超えてなんぼ。
俺も参加するage。
72 :
デフォルトの名無しさん:02/01/02 13:22
お題:微分式を得る。
例えば式 [x]x^2+3+aを入力すると(最初の[x]はxについて微分することを示す)解 2*x を得るってもの。どうよ。
ただし、割る記号 / には対応しなくて良い。
2/x は 2*x^(-1) で代用。
いや、どっちでもいいんだけど、楽なほうで。
[x]x*4+x^5 → 4+5*x^4
[x]x^(-1) → -x^(-2)
[x]sin(x) → cos(x)
[x]cos(x^2+x) → (2*x+1)*-sin(x^2+x)
むずかしいかな。
73 :
デフォルトの名無しさん:02/01/02 13:33
最大の完全数を見つけよう。
もちろん、多倍長計算アルゴリズムを利用して。
最大の完全数を見つけるアルゴリズムと、見つけた数を報告。
ちなみに、約数を全て足すと自分を超えてしまうような数の
出現状況をしらべてみてごらん。75%あたりに漸近するから。
理由はわからないけど、ちょっとおもろかった。
>>72 LISP で数十行で書けたと思う。
昔大学の授業でやった。
>>68 優先度と結合規則とオペレータのテーブル作るやりかたがある。
スタック使うけど。
>>75 それよさそう
何か配列とかで作ったスタックとループ使って関数1個でできて
規則のデータを用意するだけでいいって感じか・・
イイ・・
あー使えるーー
うまいフレームワークみたいなのつくればlex,yaccいらずになりそうだ
78 :
デフォルトの名無しさん:02/01/04 01:31
お題希望age
自分で考えろ。
80 :
デフォルトの名無しさん:02/01/04 03:34
81 :
デフォルトの名無しさん:02/01/04 04:32
>>68 つーか、lex,yaccに吐かせたコードをフレームワークにすればどー?
82 :
デフォルトの名無しさん:02/01/04 15:22
>>80 すんません・・
今あるお題をもっとがんばってみる・・・
84 :
デフォルトの名無しさん:02/01/05 19:54
個人的にプログラムでエレガントと言えるのはウイルスだと思ってるんだがどうかね?
最小限のソースコードで最大限の効果。これ以上のプログラムは無いだろう。
最小限かどうかは…
あ====
>>84 「効果=余人を驚かせる事」と考えるのは
まさにDQNの発想そのものだと思うが・・・
まともな奴なら「効果」という言葉に
もっと別の意味を見出すものだ。
期待age
89 :
デフォルトの名無しさん:02/02/05 21:06
最初のお題はどうなった?
90 :
デフォルトの名無しさん:02/02/05 22:19
int i;
:
:
if((i & (i - 1)) == 0 && i != 0){
//iは2のべき乗
}else{
//iは2のべき乗でない
}
91 :
デフォルトの名無しさん:02/02/06 17:38
>68の方法キボーン
演算子のトークンを渡してそれで分岐するとか。
93 :
デフォルトの名無しさん:02/04/05 00:48
age
>>68 >>91 アルゴリズムというか、単にステートマップ作って入力に沿って遷移させるだけじゃん。
ふつう演算子ごときで再帰処理しないって。
95 :
デフォルトの名無しさん:02/04/05 06:57
めんどくさいだけで工夫のしようがないお題はいや。
96 :
デフォルトの名無しさん:02/04/05 08:43
>>94 ん? ハードウエアのスタックを使わないって意味なのか?
状態遷移だけではどうあがいても解決できない問題だと思うが。
>>96 定義は再帰的に行うけど、実際の構文解析では再帰はしないぞ
>>97-98 ハァ? わざわざ「ハードウエアのスタックは」って断り書きをつけたんだけど?
LR解析器も自前のスタックをしっかり使っているだろうが?
電波なのか、読解力が無いのか、はたまた単なる無知なのか・・・
お題はいつも
>>1が出すんですか?
そうだとしたら
>>1が支配してるみたいで嫌だ!
Sage
102 :
デフォルトの名無しさん:02/04/05 21:59
>>94 だいたいLRとか持ち出す前に,再帰下降ですむならそっちを使うと思うが.
103 :
デフォルトの名無しさん:02/04/05 22:04
じゃぁお題。
「お題を出すプログラムを書け」エレガントな解答を求む
>>103 #include <stdio.h>
main(){printf("お題");}
@echo お題
どっかの雑誌みたいな書き方すんなよ..
107 :
デフォルトの名無しさん:02/04/05 23:07
プログラムのソースコードと全く同じ文を出力するソースを書け.
「エレガントな言語で書くコンテスト」ですか?
110 :
デフォルトの名無しさん:02/04/06 02:16
お題:論理パズル自動解析プログラム
いわゆる「正直者とウソツキ」のパズルです。ただし、本格的にやると
複雑っぽいので、以下の制約を設けます。
・登場人物は3人(A, B, C)。
・標準入力から3行分読み込み、各行を個人の発言とします
(1行目は A の発言、2行目は B の発言、3行目は C の発言)。
また、構文は解析の手間を省く為、逆ポーランド記法とします(詳細は以下の通り)。
発言 -> 主張 '\n'
主張 -> 論理和 | 論理積 | 否定 | 個人
論理和 -> 主張 主張 '|'
論理積 -> 主張 主張 '&'
否定 -> 主張 '!'
個人 -> 'A' | 'B' | 'C'
・個人の発言より推論を行い、正直者の名前を出力する事で回答します。
・推論が不可能な場合はその旨を出力します。
・なお、関数型言語の使用は禁止とします。(w
例)
入力:"A!BC&&B!AC&&|C!AB&&|\nA!AB!C!&&BA!C!&&|CA!B!&&|&\nB\n"
A:この中で、二人だけが正直者だ。
B:いや、一人だけだ。
C:その通り。
出力:""
全員ウソツキ
111 :
デフォルトの名無しさん:02/04/06 04:40
面白そうなお題ですが、なんで関数型言語はダメなの?
論理型言語がダメならともかく…。
>>110 試しに作ってみたが、「エレガントさって何?」という
根源的な疑問にぶちあたってしまった‥
push マムコ
push ティムポ
可読性
エレガントというより汗くさいな(w 長いし。
#include <stdio.h>
#define HERROR(s) do {fprintf(stderr,"error: %s\n",(s));exit(1);} while (0)
#define STAT_MAX 256
#define NUM_PERSON 3
#define STACK_MAX 64
typedef char honesty_t ; /* honesty type 0:DISHONEST 1:HONEST */
typedef struct Stack {honesty_t a[STACK_MAX] ; int d ;} Stack ; /* stack */
void Stack_init(Stack *s) { s->d = 0 ; }
int Stack_size(const Stack *s) { return s->d ; }
honesty_t Stack_pop(Stack *s) { return s->a[--(s->d)] ; }
void Stack_push(Stack *s, honesty_t h) { s->a[s->d++] = h ; }
int infer(char (* const stats)[STAT_MAX], const honesty_t *assumption) {
const char *ptr ;
int i ;
Stack stack ;
for (i = 0 ; i < NUM_PERSON ; ++i) {
Stack_init(&stack) ;
for (ptr = stats[i] ; *ptr != '\0' ; ++ptr) {
switch (*ptr) {
case '\r': case '\n': case '\t': case ' ':
break ;
case 'A': case 'B': case 'C':
Stack_push(&stack, assumption[*ptr - 'A']) ; break ;
case '!':
Stack_push(&stack, Stack_pop(&stack) ^ 1) ; break ;
case '|':
Stack_push(&stack, Stack_pop(&stack) | Stack_pop(&stack)) ; break ;
case '&':
Stack_push(&stack, Stack_pop(&stack) & Stack_pop(&stack)) ; break ;
default:
HERROR("unexpected input") ; break ;
}
}
if (Stack_size(&stack) != 1) HERROR("syntax error") ;
else if (Stack_pop(&stack) != assumption[i]) return 0 ;
}
return 1 ;
}
nt main(int argc, const char **argv) {
char stats[NUM_PERSON][STAT_MAX] ;
honesty_t assumptions[NUM_PERSON] ;
int i, j, answer = -1 ;
for (i = 0 ; i < NUM_PERSON ; ++i) fgets(stats[i], STAT_MAX, stdin) ;
for (i = 0 ; i < (1 << NUM_PERSON) ; ++i) {
for (j = 0 ; j < NUM_PERSON ; ++j) assumptions[j] = ((i >> j) & 1) ;
if (infer(stats, assumptions)) {
if (answer == -1) answer = i ;
else goto INDET ;
}
}
if (answer == -1) goto INDET ;
printf("ans.: ") ;
for (i = 0 ; i < NUM_PERSON ; ++i)
if ((answer >> i) & 1) printf("%c ", 'A' + i) ;
putchar('\n') ;
return 0 ;
INDET:
puts("Indeterminable...") ;
return 0 ;
}
/* 終わり */
>>112 これってA、B、Cの真理値を与えると入力の式の真理値を
計算するスタックマシンを作ったらほぼ出来上がりだと考えていいの?
>>119 112が自分だと気づかなくて放置してしもた、スマソ。
仕様的にはそうだと思う。総当たりで推定して、スタックマシンに検証
させる。ただそこから如何に「エレガント」に味付けしていくかじゃない?
121 :
デフォルトの名無しさん:02/04/06 12:36
レゾリューション期待age
>>120 なるほど。よくわかりました。返答ありがとうございます。
まずは後置表現のスタックマシンによる計算処理をつくって
それから、エレガント化というわけですね。
俺のように脳みそのしわが足りないやつは、とりあえず
スタートラインにならべるかどうかがしりたかっただけです。