- 2008/10/2300:00
[Perl] Perl30分間トレーニング#2
Perl30分間トレふつかめ。
今回挑んだ問題は、前回に引き続き↓これ↓。
さっそく、俺ルールのうち一つ「30分たったら、いくら途中でもそこで今日はおしまい。」を破ってしまいました;
いや、だって、すっきりしたかったんだもん!
問題6の答案
#! /usr/local/bin/perl chomp ($n = <>); &calc_DI($n, 65, 70); sub calc_DI { my ($u, @d) = @_; foreach my $i (@d) { printf "%.1f\n", ($i + 0.143 * $u - 46.3) / (0.81 + 0.0099 * $u); } }
そして、問題7なのですが、さらに40分オーバーも時間をかけて解いてみたのですが、答えが合いません・・・orz...
私の「間違っている答案」を下に晒しておきますので、どこがおかしいのか、教えてエロい人!
問題7の答案 (誤り)
#! /usr/local/bin/perl $[ = 1, $i = 1; $lu = {l=>[[1,0],[0,1]], u=>[[0,0],[0,0]]}; $z = [[0],[0]]; while (<>) { chomp $_; push (@input_data, $_); } for $j (a..f) { $p{$j} = @input_data[$i++]; } $rp = \%p; $lu -> {u} -> [1][1] = $$rp{a}; $lu -> {u} -> [1][2] = $$rp{b}; $lu -> {u} -> [2][2] = -$lu -> {u} -> [1] -> [2] * $lu -> {l} -> [2] -> [1] + $$rp{e}; $lu -> {l} -> [2][1] = $$rp{d} / $lu -> {u} -> [1] -> [1]; $z -> [1][1] = $$rp{c}; $z -> [2][1] = $$rp{f} - $lu -> {l} -> [2] -> [1] * $z -> [1] -> [1]; $y = $z -> [2] -> [1] / $lu -> {u} -> [2] -> [2]; $x = ($z -> [1] -> [1] - $lu -> {u} -> [1] -> [2] * $y) / $lu -> {u} -> [1] -> [1]; printf "%.3f, %.3f\n", $x, $y;
20行と短いですが、リファレンス(C言語でいうところのポインタ)の使い過ぎで、頭が痛くなってきました…。
#####コメント#####
- 本日のツッコミ
- たこ (2008年10月23日(Thu) 23:09)
- C++で6だけ解いてみました。
#include <iostream> #include <iomanip.h> using namespace std; int main(){ double s; cin >> s; cout << setprecision(3) << (65 - 46.3 + 0.143 * s)/(0.81 + 0.0099 * s) << "\n" << (70 - 46.3 + 0.143 * s)/(0.81 + 0.0099 * s); return 0; }
- あずま (2008年10月24日(Fri) 03:23)
- lapackをry
LU分解でぐぐるといいと思うよ。perlは読む気しないのでC#版を置いておきますね。数万点でテストしているので間違ってないはず。エラー処理は省略。
using System; class Program { const double eps = 1.0e-10; // ゼロ判定のしきい値 static void Main() { double[][] a = new double[2][] { new double[] { 1.0, 2.0 }, new double[] { 4.0, 5.0 } }; double[] b = new double[2] { 3.0, 6.0 }; double[] x = new double[2]; CalcLu(a, b, x); foreach(double d in x) Console.WriteLine(d); } static void CalcLu(double[][] a, double[] b, double[] x) { // bとxが分けてあるのは趣味 int u = a[0].Length; int v = a.Length; for(int i = 0; i < v; i++) { if(Math.Abs(a[i][i]) < eps) { // ピボット選択 for(int j = i + 1; j < v; j++) if(eps <= Math.Abs(a[j][i])) { double[] t = a[i]; a[i] = a[j]; a[j] = t; goto endPibot; } throw new Exception("解が存在しません"); } endPibot: for(int j = i + 1; j < v; j++) { double d = a[j][i] / a[i][i]; a[j][i] = d; for(int k = i + 1; k < u; k++) a[j][k] = (a[j][k] - d * a[i][k]); } } // 前進消去 double[] y = new double[v]; for(int i = 0; i < v; i++) { y[i] = b[i]; for(int j = 0; j < i; j++) y[i] -= a[i][j] * y[j]; } // 後退代入 for(int i = v - 1; 0 <= i; i--) { x[i] = y[i]; for(int j = u - 1; i < j; j--) x[i] -= a[i][j] * x[j]; x[i] /= a[i][i]; } } }
- たこ (2008年10月24日(Fri) 12:31)
- 1のソースはNYSLです
- たこ (2008年10月24日(Fri) 12:37)
-
修正しました。これもNYSLです。
#include <iostream> #include <iomanip.h> using namespace std; double tempra(double s, int d){ return (d - 46.3 + 0.143 * s)/(0.81 + 0.0099 * s); } int main(){ double s; cin >> s; cout << setprecision(3) << tempra(s, 65) << "\n" << tempra(s, 70) << endl; return 0; }
- みお (2008年10月24日(Fri) 22:03)
- > azumayaさん
すばらしい答案、ありがとうございます!。
連立方程式の解が一意に存在する、と問題文中にあるにも関わらず、解が存在するかしないかの処理まで付いていて、ものすごく丁寧なコーディングに感動しました!
> tako
「たこ」も「NYSL」だよね?
じゃぁ、たこ焼き・・・。じゅるり。 - たこ (2008年10月24日(Fri) 23:38)
- 「たこ」は食べれません><
- 2008/10/23 00:00
- 旧日記のアーカイブ
- Permalink
- nmio
- Comment(0)
comment