はてなキーワード: Readlineとは
virtualdjで出力したcueシートを、csv形式に変換するpythonスクリプトを実装してください
```python
import csv
def convert_cue_to_csv(cue_file, csv_file):
cue_data = []
with open(cue_file, 'r') as f:
# cueシートの各行を処理する
for line in f:
if line.startswith(' TRACK'):
track_data = {}
# トラック番号を取得する
track_num = line.split()[1]
track_data['Track Number'] = track_num
track_type = line.split()[2]
track_data['Track Type'] = track_type
# 次の行を処理する
# トラック名を取得する
track_name = line.split('"')[1]
track_data['Track Name'] = track_name
# 次の行を処理する
# トラックの長さを取得する
track_length = line.split()[3]
track_data['Track Length'] = track_length
cue_data.append(track_data)
with open(csv_file, 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['Track Number', 'Track Type', 'Track Name', 'Track Length'])
# ヘッダーを書き込む
writer.writeheader()
convert_cue_to_csv(cue_file, csv_file)
```
このスクリプトは、cueシートのファイルを開き、トラック情報を取得して、CSVファイルに書き込みます。トラック情報は、トラック
file = open('helloworld.py', 'r') line = file.readline() while line: print line line = file.readline()
https://github.com/kokorohamoe/OpenProfile/blob/simple/700_sample/python/helloworld.py
file = open('helloworld.py', 'r') lineno = None while lineno != file.tell(): lineno = file.tell() print file.readline()
対して違わないけど数万行だと、すごい違う
file = open('helloworld.py', 'r') line = file.readline() while line: print line line = file.readline()
何が違うか?
前のプログラムは、1行読み込んで、行番号が変わっていなければ
次のプログラムは
読み込みバッファを見て、残りがなければ終了
極簡単な違いだけど
読み込みバッファってなに?
とか、行数が数万行あったらどうするの?
おっきなプログラムだと性能が2倍3倍とかわる
それが、プログラムの怖さ
いじめないでほしいよ
file = open('helloworld.py', 'r') lwhile True line = file.readline() if not line: break print line
https://github.com/kokorohamoe/OpenProfile/blob/master/700_sample/python/helloworld.py
file = open('helloworld.py', 'r') no = None while no != file.tell(): no = file.tell() print file.readline()
これをわかりにくくはなるがPython的にシンプルに書くとこうなる
↓
https://github.com/kokorohamoe/OpenProfile/blob/simple/700_sample/python/helloworld.py
file = open('helloworld.py', 'r') line = file.readline while line: print line line = file.readline()
管理者として記名はするがコードはソングウェアとする(なんか作業中に聞いている音楽のために1曲買って)
tellってのは、行番号取得だから行番号が変わらなくなったら全部表示したから終わる というのが初心者向けコード
Pytonの機能を使って while line 行がある間ループ って書いちゃえるのが差分 ちょっと覚えることは増えるがPythonはファイル操作に便利な機能が入っているよ
初心者向けに話すのがプロ おぼえとけよ じゃない 感じろ シールドを アンプにさせよ それがアバロンの術
https://github.com/kokorohamoe/OpenProfile/blob/master/700_sample/python/helloworld.py
file = open('helloworld.py', 'r') no = None while no != file.tell(): no = file.tell() print file.readline()
プログラムはclassに記述します。たとえばSampleという名前のclassを作る場合、Sample.csファイル内に次のように書きます。(C#の場合、ファイル名とクラス名は同一でなくても良い。複数のクラスを書いても良い)
public class Sample { }
プログラムはclass内のMainメソッドの先頭から実行されます。Mainメソッドは次のように書きます。
public class Sample { public static void Main( String[] args ) { // 処理を書く } }
Console.WriteLine( "Hello world" );
コメントです。
// 一行コメント /* 複数行コメント */
// 変数 int num;
データ型です。C#のデータ型には値型と参照型とがあります。以下は値型のデータ型です。
// int(整数)型 int num; // char(文字)型 char c; // float(単精度浮動小数点)型 float val; // double(倍精度浮動小数点)型 double val; // bool(論理)型 bool flag; // DateTime(日付)型 DateTime date;
以下は参照型のデータ型です。
// String型 String s; // 配列型 String[] array;
プログラムをコンパイルするには、コマンドラインで以下のようにします。
csc Sample.cs
プログラムを実行するには、コマンドラインで以下のようにします。
Sample.exe
mono ./Sample.exe
int、float、double型の変数に数値を代入できます。int型には整数だけ代入できます。float、double型には整数でも小数でも代入できます。
int i = 2; int i = 100000000; float num = 1.234f; double num = 1.234;
四則演算です。
num = 1 + 1; num = 1 - 1; num = 1 * 2; num = 1 / 2;
商の求め方です。割る数と割られる数が両方とも整数の場合、計算結果の小数点以下が切り捨てられます。
num = 1 / 2; // 0
割る数と割られる数のどちらかが小数の場合、計算結果の小数点以下が切り捨てられません。
num = 1.0 / 2; // 0.5 num = 1 / 2.0; // 0.5 num = 1.0 / 2.0; // 0.5
余りの求め方です。
// 余り mod = 4 % 2
インクリメントとデクリメントです。
// インクリメント ++i; // デクリメント --i;
String str = "abc";
// 結合 String join = "aaa" + "bbb"; // 分割 String[] record = "aaa,bbb,ccc".Split( "," ); // 長さ int length = "abcdef".Length(); // 切り出し "abcd".Substring( 0, 2 ) // abc // 検索 int result = "abcd".IndexOf( "cd" ) // 見つかった場合はその位置、見つからなかった場合は-1が返る
配列です。
// 配列の宣言 int[] array;
配列の生成です。配列の生成時には要素数を指定するか、初期データを指定します。
int[] array; // 要素数を指定して配列を生成 array = new int[5]; // 初期データを指定して配列を生成 array = new int[] { 1, 2, 3 }; // 宣言と同時に配列を生成 int[] array2 = new int[5];
配列の要素の参照と代入です。
// 要素の参照 array[0] array[1] // 要素の代入 array[0] = 1; array[1] = 2;
array_num = array.Length;
int[] from = new int[] { 1, 2, 3 }; int[] to = new int[5]; from.CopyTo(to, 0);
if文です。
if ( 条件 ) { }
if ~ else文です。
if ( 条件 ) { } else { }
if ~ else if文です。
if ( 条件 ) { } else if ( 条件 ) { }
while文です。
int i = 0; while ( i < 5 ) { // 処理 ++i; }
for文です。
for ( int i = 0; i < 5; ++i ) { // 処理 }
int[] fields = new int[] { 1, 2, 3 }; foreach (int field in fields) { // 処理 }
C#では関数をメソッドと言います。メソッドを作るには次のようにします。戻り値を返却するにはreturn文を使います。
static int sum( int num1, int num2 ) { int total; total = num1 + num2; return total; }
ファイル入出力です。ファイル入出力を行うには、プログラムの先頭に以下を記述します。
using System.IO;
以下がファイル入力の雛形になります。ファイルのオープンや読み込みに失敗した場合、catch節に処理が移ります。
String filename = "text.txt"; StreamReader reader = null; try { reader = new StreamReader(filename); String line; while ((line = reader.ReadLine()) != null) { } } catch (IOException e) { // エラー処理: } finally { if (reader != null) { try { reader.Close(); } catch (IOException e) { } } }
またはC#ではusing ステートメントと言うものがあり、この様にも書ける
String filename = "text.txt"; using (StreamReader reader = new StreamReader(filename)) { try { String line; while ((line = reader.ReadLine()) != null) { // 読み込んだ行を処理 } } catch (IOException e) { // エラー処理: } }
usingをつかうとCloseがなくなったことからわかるようにusing(){}を抜けるときに自動的にDisposeメソッドを呼び出し、オブジェクトを廃棄する。その分コードがスッキリするが、使いにくい場面もあるので考えて使うこと。
以下がファイル出力の雛形になります。ファイルのオープンや書き込みに失敗した場合、catch節に処理が移ります。
String filename = "text.txt"; StreamWriter writer = null; try { writer = new StreamWriter(filename)); writer.WriteLine("abc"); writer.WriteLine("def"); writer.WriteLine("fgh"); } catch (IOException e) { // エラー処理: } finally { if (writer != null) { writer.Close(); } }
こちらもusingを使って書ける。が、割愛する。
C#でよく出てくる知っておいたほうがよい文法の一覧です。
繰り返し文の途中で抜けるにはbreak文を使用します。
for ( i = 0; i < 5; ++i ) { if ( 条件 ) { break; // 条件を満たす場合、for文を抜ける。 } }
残りの部分処理をスキップし、次の繰り返しに進むにはcontinue文を使用します。
for ( i = 0; i < 5; ++i ) { if ( 条件 ) { continue; // 条件を満たす場合、残りの部分処理をスキップし、次の繰り返しに進む。 } }
例外を投げるにはthrow文を使用します。
throw new Exception( "Error messsage" );
try { // 例外が発生する可能性のある処理 } catch ( Exception e ) { // 例外発生時の処理 }
http://okajima.air-nifty.com/b/2010/01/post-abc6.html
迷路の最短経路を求める問題が出たので解いてみた
幅優先探索を使えばいいのがわかっていたのですんなりかけたのだが、無限ループになる個所があったので動くようになるまで時間がかかった
using System; using System.Collections.Generic; using System.Text; using System.Linq; namespace MazeFind { class Point { public int x; public int y; public Point before; public Point(int x, int y,Point before) { this.x = x; this.y = y; this.before = before; } } class Program { static void Main(string[] args) { const char BreakChar = 'B'; const char GoalChar = 'G'; const char WallChar = '*'; const char BeforeChar = '.'; StringBuilder[] maze = new StringBuilder[]{ new StringBuilder("**************************"), new StringBuilder("*S* * *"), new StringBuilder("* * * * ************* *"), new StringBuilder("* * * ************ *"), new StringBuilder("* * *"), new StringBuilder("************** ***********"), new StringBuilder("* *"), new StringBuilder("** ***********************"), new StringBuilder("* * G *"), new StringBuilder("* * *********** * *"), new StringBuilder("* * ******* * *"), new StringBuilder("* * *"), new StringBuilder("**************************"), }; Point start = new Point(1, 1,null); //最短経路を探索する Queue<Point> queque = new Queue<Point>(); queque.Enqueue(start); while (queque.Count > 0) { Point now = queque.Dequeue(); if (maze[now.y][now.x] == BreakChar) Console.WriteLine("break"); if (maze[now.y][now.x] == WallChar || maze[now.y][now.x] == BeforeChar) continue; else if (maze[now.y][now.x] == GoalChar) { Point p = now.before; while (p != null) { maze[p.y][p.x] = '@'; p = p.before; } break; } if (maze[now.y - 1][now.x] != '#') { queque.Enqueue(new Point(now.x, now.y - 1, now)); maze[now.y][now.x] = '.'; } if (maze[now.y][now.x + 1] != '#') { queque.Enqueue(new Point(now.x + 1, now.y, now)); maze[now.y][now.x] = '.'; } if (maze[now.y + 1][now.x] != '#') { queque.Enqueue(new Point(now.x, now.y + 1, now)); maze[now.y][now.x] = '.'; } if (maze[now.y][now.x - 1] != '#') { queque.Enqueue(new Point(now.x - 1, now.y, now)); maze[now.y][now.x] = '.'; } } //結果を出力する foreach (StringBuilder s in maze) Console.WriteLine(s.ToString().Replace(BeforeChar,' ')); Console.ReadLine(); } } } <||
これで40分。
タイムアタックってことでアルゴリズムは全幅探索で書き上げました。
エラーチェック皆無。
A*ならもう5分ほど延びるかな?
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace Maze { class Program { // 探索用地図 static int[,] maze; // 始点終点 static Position Start = new Position(0, 0), Goal = new Position(0, 0); static void Main(string[] args) { //////////////////////////// まずは各行のリストとして読み込み string[] inMaze; using (var fp = new FileStream(args[0], FileMode.Open, FileAccess.Read)) using (var iStream = new StreamReader(fp)) inMaze = iStream.ReadToEnd().Split('\n'); // 迷路幅 int height = inMaze.Length; // 迷路高さ int width = inMaze[0].Length; /////////////////////////// 読み込んだ迷路を作業用地図に展開 maze = new int[width, height]; for (int y = 0; y < height; ++y) { string line = inMaze[y]; for (int x = 0; x < line.Length; ++x) { maze[x, y] = line[x] == '*' ? -1 : 0; if (line[x] == 'S') Start = new Position(x, y); if (line[x] == 'G') Goal = new Position(x, y); } } // 探索実行 int dist = Search(maze, Start); // 探索結果から最短経路を再現 Position backTracer = Goal; while (dist>1){ --dist; backTracer = backTracer.Nearbys.First(pos => maze[pos.X,pos.Y] == dist); maze[backTracer.X, backTracer.Y] = -2; } //////////////////// 最短経路こみのアスキー地図に変換 char[,] outMaze = new char[width, height]; for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { outMaze[x, y] = maze[x, y] == -2 ? '$' : maze[x, y] == -1 ? '*' : ' '; } } outMaze[Start.X, Start.Y] = 'S'; outMaze[Goal.X, Goal.Y] = 'G'; ////////////////////// 結果は標準出力に。 for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) Console.Write(outMaze[x, y]); Console.WriteLine(); } Console.ReadLine(); } /// <summary> /// 探索する。SG間の道のりを返す(道のり=SGが隣接しているなら1) /// </summary> private static int Search(int[,] maze, Position Start) { List<Position> FrontLine = new List<Position>(); FrontLine.Add(Start); int dist = 1; for (; ; ) { List<Position> NextFrontLine = new List<Position>(); foreach (var pos in FrontLine) { foreach (var nextPos in pos.Nearbys) { if (nextPos == Goal) return dist; if (maze[nextPos.X, nextPos.Y] == 0) { maze[nextPos.X, nextPos.Y] = dist; NextFrontLine.Add(nextPos); } } } FrontLine = NextFrontLine; ++dist; } } } struct Position { public readonly int X, Y; public Position(int x, int y) { X = x; Y = y; } public IEnumerable<Position> Nearbys { get { return new[]{ new Position(X-1,Y), new Position(X,Y-1), new Position(X+1,Y), new Position(X,Y+1), }; } } public static bool operator==(Position p1, Position p2){ return p1.X == p2.X && p1.Y == p2.Y; } public static bool operator!=(Position p1, Position p2){ return p1.X != p2.X || p1.Y != p2.Y; } } }
少し遅れた感があるけど、解いてみた。
出力がテキストでないけど・・・。
仕事の合間を使ってやったものの、昼前に始めたのが5時頃にようやくできる程度。
これを25分とは尋常じゃないな、大口叩くだけあってよっぽど優秀なんだろう。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=shift_jis"> <meta http-equiv="Content-Language" content="ja"> <meta http-equiv="Content-Script-Type" content="text/javascript"> <meta http-equiv="Content-Style-Type" content="text/css"> <style type="text/css"> <!-- pre { font-family: monospace; } --> </style> <script type="text/javascript"> <!-- window.onload = function() { var q = new Map(); q.load("maptest.txt"); q.search(); var answer = document.getElementsByTagName("pre").item(0); var answerText = "\r\n"; for(var ix = 0; ix < q.route.length; ix++) { answerText += q.route[ix].join("") + "\r\n"; } answer.firstChild.data = answerText; alert("終了しました。"); }; /** マップオブジェクト */ function Map() { this.ymap = []; this.route = []; } //マップの読み込み Map.prototype.load = function(filePath) { //ファイルシステム var fileSystem = new ActiveXObject("Scripting.FileSystemObject"); //ファイル読み込み var file = fileSystem.OpenTextFile(filePath); while(!file.AtEndOfLine) { var fileBuffer = file.ReadLine(); this.ymap.push(fileBuffer.split("")); } file.Close(); fileSystem = null; }; //マップの探索 Map.prototype.search = function() { var that = this; //マップコピー var ymap = this.ymap.concat(); for(var y = 0; y < ymap.length; y++) { ymap[y] = ymap[y].concat(); for(var x = 0; x < ymap[y].length; x++) { if(ymap[y][x] == "S") var start = new MapNode(y, x); if(ymap[y][x] == "G") var goal = new MapNode(y, x); } } var openList = []; var closeList = []; start.costf = start.distance(goal); openList.push(start); //経路探索 while(openList.length > 0) { var node = openList.shift(); //探索終了 if(goal.equal(node)) { createRoute(node); break; } closeList.push(node); //隣接ノードの作成 var tonari = []; if( ymap[node.positionY][node.positionX - 1] == " " || ymap[node.positionY][node.positionX - 1] == "G" ) tonari.push(new MapNode(node.positionY, node.positionX - 1, node)); if( ymap[node.positionY - 1][node.positionX] == " " || ymap[node.positionY - 1][node.positionX] == "G" ) tonari.push(new MapNode(node.positionY - 1, node.positionX, node)); if( ymap[node.positionY][node.positionX + 1] == " " || ymap[node.positionY][node.positionX + 1] == "G" ) tonari.push(new MapNode(node.positionY, node.positionX + 1, node)); if( ymap[node.positionY + 1][node.positionX] == " " || ymap[node.positionY + 1][node.positionX] == "G" ) tonari.push(new MapNode(node.positionY + 1, node.positionX, node)); //隣接ノードの検索 for(var tx = 0; tx < tonari.length; tx++) { var openIn = false; var closeIn = false; tonari[tx].cost = node.cost + 1; var costf = tonari[tx].cost + tonari[tx].distance(goal); tonari[tx].costf = costf; //オープンリストから検索し入れ替える。 for(var ox = 0; ox < openList.length; ox++) { if(tonari[tx].equal(openList[ox])) { openIn = true; if(costf < openList[ox].costf) { openList.splice(ox, 1); push(openList, tonari[tx]); } break; } } //クローズリストから検索し、オープンリストへ移す。 for(var cx = 0; cx < closeList.length; cx++) { if(tonari[tx].equal(closeList[cx])) { closeIn = true; if(costf < closeList[cx].costf) { closeList.splice(cx, 1); push(openList, tonari[tx]); } break; } } //どちらにもない場合、オープンリストへ追加する。 if(!openIn &amp;&amp; !closeIn) push(openList, tonari[tx]); } } //適切な位置に追加する。 function push(array, item) { for(var ix = 0; ix < array.length; ix++) { if(item.costf < array[ix].costf) { array.splice(ix, 0, item); return; } } array.push(item); } //ルートマップの作成 function createRoute(lastNode) { var node = lastNode.parent; while(node.parent) { ymap[node.positionY][node.positionX] = "$"; node = node.parent; } that.route = ymap; } }; /** マップノード */ function MapNode(y, x, parentNode) { this.positionY = y; this.positionX = x; this.parent = parentNode; this.cost = 0; this.costf = 0; } //同一ノードかチェックする。 MapNode.prototype.equal = function(targetNode) { if( this.positionY == targetNode.positionY &amp;&amp; this.positionX == targetNode.positionX ) return true; return false; }; //直線距離を求める。 MapNode.prototype.distance = function(targetNode) { sabunY = this.positionY - targetNode.positionY; sabunX = this.positionX - targetNode.positionX; return sabunY ^ 2 + sabunX ^ 2; }; // --> </script> <title>経路探索:A*</title> </head> <body> <pre>&nbsp;</pre> </body> </html>
http://www.ruby-lang.org/ja/news/2009/01/30/ruby-1-9-1-released/
まあ、ライブラリがぜんぜん1.9に対応してないから今すぐ1.8から移行するなんてことはできないんだけど、こうやって安定版を出せばライブラリの移行を促せるんだから、ちょうど鶏が先か卵が先かみたいなもんで、リリースすることに意味があるんだよね。
ところで、Ruby といえば、そのままコマンドラインで ruby を使っている人はあんまりいなくて、普通は irb を使うよね。でも、単に ruby を自分のホームディレクトリで make しただけだと、当然、irb は使えないんだ。でもこれだけためにインストールするのは嫌。そこでどうするか?
実は最近の ruby の Makefile には作ったばっかりの ruby をライブラリパス込みで動作させるコードが入ってる。これを使って irb を動かしてみるというのが今回のハックのネタというわけ。
masuda@localhost:~/ruby-1.9.1-p0 $ make (ruby の make はすべて終了したとする) masuda@localhost:~/ruby-1.9.1-p0 $ cat > test.rb require 'irb' require 'irb/completion' IRB.start ^D (^D はCtrl-dで入力終了のこと。普通は表示されない) masuda@localhost:~/ruby-1.9.1-p0 $ make runruby ./miniruby -I./lib -I.ext/common -I./- -r./ext/purelib.rb ./runruby.rb --extout=.ext -- ./test.rb irb(main):001:0> puts "Have a fun!"
これで適切なライブラリパスが指定されて、その場で最新の ruby が使い放題だ。Readlineを使ってるから編集も楽だし、マジおすすめ。
お、いらっしゃいましたか。
このコードのコンセプトは、「馬鹿でかいファイルから幾つかの特定行を参照するにあたり、なるべくディスクIOを減らしつつメモリ消費も押える」と解釈したけどあってるのかな?
キャッシュした行番号はソートしたリストにしておけばバイナリサーチで比較的早く最近傍を見つけることができるし、見つけた場所へ今回キャッシュした行を挿入すればソートが維持できる。
キャッシュの大きさにもよるけれど、シークしながら探すより、オンメモリで探す方が早い気がする。そういうモジュールがすでにあるかも知れないし。
キャッシュがでかくなるなら、いっそ全部読んじゃった方が良いかも知れないし、でかいならDB使っちゃった方が効率的かも知れない。
その辺はアクセスパターンや規模や行長のバラツキやあれやによるからなんともいえないけれど。
ところで、実はruby知らないんで聞くんだけど。
なんかデーターが見つからない危険性を感じるというか。ファイルがでかいからreadlinesとか使いたくないんだけれども無理かな。
class Id_sorted_data def initialize path, avarage_bytes_by_one_data, search_margin @f = File.open(path); @v = avarage_bytes_by_one_data; @cash = {}; @margin = search_margin; return self end def read number if @cash.member?(number) return @cash[number]; end @f.seek([(number - @margin) * @v, 0].max); for i in 1..20 @f.readline; temp = @f.readline; @cash[temp.to_i] = temp; if temp.to_i == number return @cash[number]; elsif (number - @margin .. number).include?(temp.to_i) return near(number); end @f.seek((number - temp.to_i - @margin) * (@v * (20 - i) / 20), IO::SEEK_CUR); end end def near number for i in 1..@margin temp = @f.readline; @cash[temp.to_i] = temp; if temp.to_i == number return @cash[number]; end end end end
@data=(a,b,c);print@data
#!/usr/bin/perl use strict; my @data = qw(a b c); my $cx = scalar @data; my $si = 0; my $ax; LOOP: $ax = $data[$si]; print $ax; $si++; not --$cx or goto LOOP;
#!/usr/bin/perl use strict; my @data = qw(a b c); package AtoH; use base qw(Tie::Handle); sub TIEHANDLE { my $class = shift; return bless {data => [@_]}, $class; } sub READLINE { return shift @{shift->{data}}; } package main; tie *ARGV, 'AtoH', @data; while (<>) { print; }