2013年12月15日日曜日

Paizaのオンラインハッカソンに参加してみた

ちょっと前に話題になったpaizaのオンラインハッカソンに参加してみました。

とりあえず言語はjavaを選択。下記のような方針でコードを書きました。

1. 商品の金額データを昇順にソートする。
2. ソート済みのデータに対して先頭と後尾から挟み撃ちで検索をかけ、指定されたキャンペーン金額以下の最大値を検索する。

計算量は1がN(O*logN)で2がO(N)。なので全体としてはN(O*logN)になります。
2の探索はbinary searchを利用すればもう少し早くなりそうですが、どのみち1のソートでO(N*logN)かかるので、手を抜きました。

実際に書いたコードは次のようになります。







import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;


public class Main {

    public static void quickSort(int[] arr, int left, int right){
        if (left <= right) {
            int p = arr[(left+right) / 2];
            int l = left;
            int r = right;
            
            while(l <= r) {
                while(arr[l] < p){ l++; }
                while(arr[r] > p){ r--; }
                
                if (l <= r) {
                    int tmp = arr[l];
                    arr[l] = arr[r];
                    arr[r] = tmp;
                    l++; 
                    r--;
                }
            }
    
            quickSort(arr, left, r);
            quickSort(arr, l, right);
        }
    }
 public static void main(String args[]){

     try {
         BufferedReader br = 
           new BufferedReader(new InputStreamReader(System.in));         

         String nd[] = br.readLine().split(" ");
         int n = Integer.parseInt(nd[0]);
         int d = Integer.parseInt(nd[1]);
         
         int narr[] = new int[n];
         
         int min = Integer.MAX_VALUE;
         for(int i = 0; i < n; i++){
          int a = Integer.parseInt(br.readLine());          
          if(a < min){
           min = a;
          }
          
          narr[i] = a;

         }
         
         quickSort(narr,0,n-1);
         for(int i = 0; i < d; i++){
          
          int a = Integer.parseInt(br.readLine());          
          if(a <= min * 2){
           System.out.println(0);
          }else{
           int start = 0;
           int end = n -1;
           int max = 0;
           while(start < end){
            int sum = narr[start] + narr[end];
            if(sum <= a && sum > max) max = sum;
            
            if(sum == a){

             break;
            }
            if(sum > a){
             end--;
            }else{
             start++;
            }
           }
           System.out.println(max);
            
          }
         }

     } catch (Exception e) {
      e.printStackTrace();
         System.err.println("Error:" + e.getMessage());
     }

 }
}


結果を見ると無事case3まで実行完了できているようでした。

Test case 1 通過 実行時間:0.08 秒
Test case 2 通過 実行時間:0.09 秒
Test case 3 通過 実行時間:0.22 秒

と、クリアしてしまったので、ここで満足しちゃいましたが、この先更に速度を挙げためのアイデアがいくつか考えられます。

1. 探索をbinary searchにする
2. 探索時に一度探索したデータをキャッシュ化して覚えておく。ただしキャンペーン日数が75しかないので、今回のデータセットではあまり効果が薄いかもしれません。

参考文献

1. 「クイックソートのサンプルコード」
http://homepage3.nifty.com/teranet/JavaAlgorithm/QuickSort.html

2013年11月26日火曜日

在中日本人108人のそれでも私たちが中国に住む理由

第1章 あのデモがあった日
第2章 それでも「日本」が要る!
第3章 暮らしのなかの「島」問題
第4章 日中の誤解を生むもの
第5章 「反日」下のビジネス
第6章 国境を超え伝える
第7章 隣人との未来へ




悪化する日中関係のさなかにおいて、中国に住む日本人は日々友人や家族から安否を気遣われている。日本のメディアを通してみる反日としての中国は、攻撃的で破壊的であるようにしか映らない。

しかしながら現地に住む日本人によれば、日本のメディアで報じられているほど危険な状態ではなく、またすべての中国人が日本嫌いなわけではなく、親日的な人たちも少なからずいるとのことだ。

本書ではそのような現地の人達の声をまとめた本である。

本を読むについて、日本人と接触したことがなく、反日教育の影響でただ当然のように日本を嫌っている中国の現状が窺えてくる。そのため、わずか数分の日本人との交流で、急に友好的な態度に改める者も少なくないようであり、そのような記述が随所に描かれている。実態を知らないからこそ、盲目的に嫌うことが出来るのであろう。

確かに、私自身を思い返して中国に大してマイナスなイメージを持っていないのは、日本で知り合った多くの中国人留学生のおかげである。彼ら彼女らが非常に友好的で、なんら日本人と変わらず付き合えることを知っているし、今でも同じ職場で仕事をしているおかげで、日本のメディアの報道を客観的に受け止められているといえる。

そう考えると、国レベルではなく、個人レベルでの日中交流は、決して絶やしては行けないのかもしれない。ここまで関係が悪化すると実現自体のハードルも高くなるが、だからこそ、最低限のできることとして人と人との交友は絶えないことを願いたい。

一方でそうは言うものの、日本人というだけでタクシーの乗車拒否をしたり、安全確保の名目のためとはいえ、有事には公共の場で日本語を使うのをやめるように警察から指示されるなど、冷静に考えれば異様な事態である。本書の中の人物はどなたも淡々と受け止めている様子だが、部外者の私には侮辱にも程があるように感じる。もはや反日は中国にとって文化や条件反射にさえ感じられ、関係改善は相当路が険しいと感じた。

2013年11月19日火曜日

Google App Engineのデータをエクスポートする方法

iOSのランキングを日々取得しているiOSランキングトラッカーは、無課金のGoole App Engineで動かしていますが、そろそろ容量の上限値1Gに達しそうな勢いです。

収益があるわけでもない、ただの趣味Webサービスに金をかけることも出来ないので、古いデータを外出しする方法を調べてみました。

今回はそのうち、Google App EngineのBigQuery上にあるデータを手元のデスクトップPCにコピーする手順を紹介します。

1. app.yamlを編集する

下記の二行を追加する。

builtins:
- remote_api: on

2. コマンドを実行してアプリケーションを更新する。

<GAEのインストールパス>/appcfg.py update <app-directory>
注: <app-directory>は直下にapp.yamlがおいてあるディレクトリを指定する必要がある。


3. コピーの実行

%><gae-install-dir>/appcfg.py download_data --application=<app-id> --url=http://<appname>.appspot.com/[remote_api_path] --filename=<data-filename>
<app-id>はapp.yamlに定義した"application"の値。
ただし、high-replication datastoreを使ってる場合、appidの先頭にs~をつける必要がある。
例) applicationの値がexampleで、high-replication datastoreを使ってる場合は下記のようになる。
%><gae-install-dir>/appcfg.py download_data --application=s~example --url=http://example.appspot.com/_ah/remote_api --filename=/tmp

補足

どうやら、このコマンド実行もDataStoreのリクエスト制限の対象のようで、OverQutaErrorが出てしまいました。
OverQuotaError: The API call datastore_v3.RunQuery() required more quota than is available.
 このような場合は下記のようにkindを指定したほうがよさそうです。
%><gae-install-dir>/appcfg.py download_data --application=example --kind=<kind> --url=http://example.appspot.com/_ah/remote_api --filename=/tmp

参考文献

データのアップロードとダウンロード

2013年11月10日日曜日

第一回AI麻雀大会開催しました

先日公開したAI麻雀サーバを利用して第一回AI麻雀大会を開きました。

第一回ということでとりあえず都合のついた二人だけで対戦しました。

まずユーザのプロフィール紹介。

ユーザ名 戦略の概要
developing 喰いタンのみ、役牌のみなどを狙い誰よりも早く上がることを目指す
shizimily7 シャンテン数が一番小さくなるものを計算して捨て牌を選択。役があるかは考慮せず リーチを掛けることによって最低限の役を確保する戦略

そして結果の概要。

ユーザ名 勝利回数
developing 5
shizimily7 93
*引き分け 2回


100回行った対戦の平均点数は次のようになりました。
ユーザ名 平均点数
developing 22942
shizimily7 30638
sampleAI1 22368
sampleAI2 22056


結果としてはshizimily7の圧勝。結果を解析すると、上がり回数、平均上がり得点ともにdevelopingより優秀。特に普通に 七対子や大三元を上がるなどソツのない優秀なAIに仕上がる。developingは鳴きを駆使して早上がりを目指す戦略にであったが上がり回数でも shizimily7を下回っていることを考えると、もう少しプログラムの作り込みに期待したいところ。      

2013年11月1日金曜日

麻雀のAIサーバ作りました

麻雀のAI(Artificial intelligence)サーバを作りました。

https://github.com/kentan/SmartBird

最近では電王戦と称した将棋のAIが話題ですが、
麻雀のAIを作っていろいろ遊んでみたくしてみたくなり、このたびAIサーバを作成してみました。

将棋・チェス・碁などはいわゆる「二人ゼロ和有限確定完全情報ゲーム」と呼ばれるもので、

簡単にいうと、下記のようなゲームのことを意味します。


  • 一方の負け点数が他方の勝ち点数になる(二人ゼロ和)
  • 戦略の数が有限(有限)
  • サイコロをふるなどの運要素がない(確定)
  • 戦略を判断するための情報を全部知ることが出来る(完全情報)



有限で完全情報であるゲームは基本的にコンピュータのリソースをふんだんに使うと強くなります。
10年ほど前にはプロの相手にならなかった将棋のAIがちらほら勝てるようになったのもそのためです。

それに対し、麻雀は


  • 4人ゲーム(Not 二人ゼロ和)
  • 次に選択できる手が(ツモる牌)が確定的でない(Not 確定)
  • 戦略を決定するための情報のほとんどを知ることが出来ない(Not 完全情報)


といった特徴があり、将棋や碁よりもAIの難易度が高いといえます。






2013年10月15日火曜日

App Ranking HIstoryにチャート機能を実装した

AppleのRSSからiPhoneアプリのランキングを取得するApp Ranking Historyにチャートを導入してみました。

気になるアプリのランキング推移をチャートで確認できます。



google chart apiを使って作りました。
定番のchartはひと通り揃ってていい感じです。

一応スマフォでも見れるようには作りましたが、レイアウトとか見栄えが若干いまいち。

iPhoneのサファリで株価とかgoogle検索すると綺麗に表示されるんだけど、これはどうやってるんだろうか。これもgoogle chart apiつかってるのだろうか。




ところで、このサービス、暇な時にちょこちょこいじってましたが、ここまで来ると次はアプリ名で検索とかしたくなりますね。まあそれは気が向いた時にでもやってみます。

2013年8月4日日曜日

iOSアプリトラッカー アップデートしました

前にブログで紹介したiTunesストアで1位をとったアプリを時系列で表示させるiOSアプリトラッカーをちょっとだけ機能拡張しました。

今回の修正では1位だけじゃなくて2位以降も表示出来るようにしました。






日付のところをクリックすると、今まではiTunesストアのアプリページに飛んでいたのですが、今回からは次のような画面に遷移して2位以降のアプリも見ることができます。

2013年7月16日火曜日

Kotlinはじめました。

IntelliJ IDEAで有名なjetbrains社が推進しているスクリプト言語Kotlin始めました。

Kotlinは静的型付けのJVM上で動作するスクリプト( statically-typed JVM-targeted programming language)です。


公式サイトによると、以下の項目を開発のゴールとしている。
  • Java互換の言語であること
  • Javaと同等の実行速度であること
  • NullPointerError Exceptionの静的にチェックによりJavaより安全であること
  • 動的型推論、高階関数、extension functionなど様々な機能による豊か、かつ簡潔な表現力をもつこと

ふーむ。ということでとりあえず書いてみる。Hello World。


package demo 
 
fun main(args : Array<string>) { 
  println("Hello, world!") 
}

しかし、さすがにHello Worldしただけじゃ面白くないので、15 puzzle書いてみた。
ただの反復深化です。枝狩りなし。githubはこっち




package demo
 
fun main(args : Array<string>) {
    val data = array(1,2,3,0,5,6,7,4,9,10,11,8,13,14,15,12);
    var limit:Int = 0;
    var LIMIT_MAX:Int = 20;
    while(limit <= LIMIT_MAX){
        print(limit);
        if(run(data,0,-1,limit)){
            break;
        }
        limit += 1;
    }
}
 
fun search_white_space_pos(data : Array<int>):Int{
    for(i in data.indices){
        if(data[i] == 0){
            return i;
        }
    }
    return -1;
}
 
fun finish(data : Array<int>):Boolean{
    for(i:Int in data.indices){
    if(i == 15){
        if(data[i] == 0){
            return true;
        }else{
            return false;
        }
    }else{
        if(data[i] == i + 1){
            continue;
        }
        return false;
    }
}
return true;
}
 
fun is_move_down(white_space_pos:Int):Boolean{
    if(white_space_pos >= 12 && white_space_pos <= 15){
        return false;
    }
    return true;
}
fun is_move_up(white_space_pos:Int):Boolean{
    if(white_space_pos >= 0 && white_space_pos <= 3){
        return false;
    }
    return true;
}
fun is_move_left(white_space_pos:Int):Boolean{
    if(white_space_pos == 0 || white_space_pos == 4 || white_space_pos == 8 || white_space_pos == 12){
        return false;
    }
    return true;
}
fun is_move_right(white_space_pos:Int):Boolean{
    if(white_space_pos == 3 || white_space_pos == 7 || white_space_pos == 9 || white_space_pos == 15){
        return false;
    }
    return true;
}
fun swap(data:Array<int>,pos1:Int,pos2:Int){
    var temp:Int = data[pos2];
    data[pos2] = data[pos1];
    data[pos1] = temp;
}
 
fun show(data:Array<int>){
    for(d in data){
        print(d);
        print(" ");
    }
    println();
}
 
fun run(data : Array<int>,depth:Int,previous:Int,limit:Int):Boolean{
    var white_space_pos:Int = search_white_space_pos(data);
 
    if(depth > limit){
 
        return false;
    }
    if(finish(data)){
        println("found");
        show(data);
        return true;
    }
    if(previous != 1 && is_move_down(white_space_pos)){
        swap(data,white_space_pos,white_space_pos + 4);
        if(run(data,depth + 1,0,limit)){
            return true;
        }
        swap(data,white_space_pos + 4,white_space_pos);
    }
    if(previous != 0 && is_move_up(white_space_pos)){
        swap(data,white_space_pos,white_space_pos - 4);
        if(run(data,depth + 1,1,limit)){
            return false;
        }
        swap(data,white_space_pos - 4,white_space_pos);
    }
    if(previous != 3 && is_move_left(white_space_pos)){
        swap(data,white_space_pos,white_space_pos - 1);
        if(run(data,depth + 1,2,limit)){
            return false;
        }
        swap(data,white_space_pos - 1,white_space_pos);
    }
    if(previous != 2 && is_move_right(white_space_pos)){
        swap(data,white_space_pos,white_space_pos + 1);
        if(run(data,depth + 1,3,limit)){
            return false;
        }
        swap(data,white_space_pos + 1,white_space_pos);
    }
    return false;
}

Kotlinっぽい機能全く使ってないけど、普通のjavascriptでも書いてる気分でかけました。とりあえずとっつきやすそう。

参考文献


2013年7月10日水曜日

LEAN IN(リーン・イン) 女性、仕事、リーダーへの意欲



1 怖がらなければ何ができる?
2 同じテーブルに着く
3 できる女は嫌われる
4 梯子ではなくジャングルジム
5 メンターになってくれませんか?
6 本音のコミュニケーション
7 辞めなければならないときまで辞めないで
9 スーパーママ神話
10 声を上げよう
11 ともに力を


FacebookのCOOであるシェリル・サンドバーグが書いた女性のキャリアについての本。

先日日本語版も発売され、Amazonのランキング上位をキープし続けているようだ。

日本のメディアを通して見るアメリカは、女性の活躍に対して好意的であり先進的であるように思っていた。数字でこそまだまだ社会進出の割合が低いようだが、これは時間の問題であり20年後にはすんなりと多くの女性が社会の重要な地位を占めるのだろうと思っていた。

しかし、本書によれば、日本とそう変わらず、家事・育児が女性が行うことを前提とする社会的風潮や、仕事に対して活発な女性に対するネガティブな捉え方、またキャリアアップのチャンスを自ら逃してしまう要因が存在するとのことだ。

これらについて本書では興味深い研究事例が紹介されている。

10年ほどまえ、ビジネススクールの学生たちを2つのグループに分け、とあるビジネスパーソンが人脈を駆使して投資家として成功しようとしている事例を読ませた。その上で、その人に対してどのような印象を持ったか感想を述べてもらうという実験が行われた。

2つのグループに渡された事例は全く同じであるが、主人公の名前だけ変えられている。
一方は女性の名前の主人公で、他方は男性の名前の主人公であった。

結果、男性の名前が書かれた事例を読んだグループは主人公に対して好意的な印象を持ち、ともに働きたいとコメントをしたのに対し、女性の名前が書かれた事例を読んだグループは、否定的な印象を持ち、仕事をともにすることを嫌がった。

男性は仕事の評価と個人の評価が正の相関を持つのに対し、女性は負の相関を持つという、驚きつつも胸に手を当てて見れば、そことなく腑に落ちる結論が導かれている。


また周囲の人間の評価以外にも、不利な要素が潜む。

本書によれば、総じて自分に対する評価というものは、女性よりも男性のほうが高い傾向にあるとのことだ。客観的に見れば同程度だとしても、男性は自分を高く評価する傾向にある。

このため、何か新しいチャンスが有った時、積極的に飛びつくのは圧倒的に男性が多い。
そしてその結果、成果を出すのも男性が多くなる。こちらも言われてみれば心当たりのある話しである。


本書を非常に興味深い気持ちで読ませてもらったが、これを読んだ後、アメリカ人はどう考えてるのかとても気になった。

Amazon.comのレビューでは次のようなレビューが寄せられている。評価の高い好意的なレビュー2件ほどから抜粋する。

The best message to take from this book is to be aware of what is going on in the workplace. Take the opportunity to change the inequality. Don't wait for someone to "fix" things for you. When opportunities present themselves jump on them if it's what you want. Take control.  

I found myself in every chapter she wrote. I feel that her advices directly address my insecurity and help me find strength to move on to bigger and better things. 

彼女に共感し、これを変化の契機としよう、という意見だ。高評価のレビューは概ねこのような意見が多かった。

2013年7月9日時点で、総計で1123のレビューが寄せられ、注目の高さが伺われる。
そのうち、963件が星4つ以上であるので、米国では好意的な問題提起として捉えられているのだろう。


個人的にあこのような本を読んでいつも心配になるのは、変化の流れをすべての人間に当てはめようとする人が現れることである。とりわけメディアは女性の社会進出を煽り、すべての女性は仕事を家庭を両立しなければならないかのように掻き立てる。

この懸念については本書でもところどころ触れられているが、問題の解決の際には個人の志向性を最大限尊重させながら取り組む必要があるだろう。


シェリル・サンドバーグ自身も問題は多数あれど解決は困難なことを認めている。
それでも女性が政治、産業のトップにもっと進出することによって、世の中が良くなることを渇望している。

私自身も、すべての人が望む生活をおくるのに支障が少しでも少ない世の中になるのはとてもいい事だと思う。





 TEDで講演した時の動画。

2013年5月5日日曜日

javaからscalaを呼び出すサンプルプログラム

最近話題のscala。

コンパイル結果が.classファイルになるので、javaから普通に呼び出すことが出来るみたいです。

なので、scalaのコードをコンパイルして、jarを生成し、そのjarをjavaから呼び出すサンプルプログラムを書いてみました。

まずscalaのコード。

object JarMain {
    def main(args:Array[String]) = {
     println("Hi, I am Scala.");
     println("I've got your message:");
     for (elem <- args) println("> " + elem);
    }
}

これをscalaでコンパイルした後、javaのコマンドを用いてjarを生成する。

それを呼び出すjavaのコードは下記のよう。

public class Main {
 public static void main(String args[]){

  String[] strs={"Hi, I'm Java"};
  JarMain.main(strs);
 }
}

で、実行結果
Hi, I am Scala.
I've got your message:
> Hi, I'm Java

簡単。そして地味にすごい。

最終的にjarに落としこむことができるので、ひとつのjavaプロジェクトの中で一部分だけscalaで書くということが簡単に実現できる。

これはtraditionalで大規模な開発を行なっている企業には特に嬉しい。
一つのプロジェクトで一部分だけscalaでスモールスタートして、様子を検証しつつ、上手く行ったら徐々にscalaに置き換えていくストーリーが実現可能になる。

この点は非常に重要で、例えば一昔まえに流行ったruby on railsなんかだと、導入するとなったら全部変えなきゃいけないので、アーキテクチャ全体の変更が必要だわ、多数のエンジニアの教育が必要だわ、とかくtraditionalな会社では導入の敷居がかなり高かった。

でもscalaならまずは最小限からスタートさせて徐々にjavaを置き換えていくということも簡単に出来るので、保守的かつ大規模に開発している企業とかでも容易に導入が進みそう。




ランキング1位のiPhoneアプリの履歴を表示するサービス作ってみた

定期的に新しいアプリが話題に上がってくるiPhoneアプリ。
毎日App Storeを眺めてても面白いんですが、忙しくなるとしばらく見ないこともしばしば。

なので、ランキング1位のアプリを毎日記録して一覧表示するサービスを作ってみました。


iPhoneアプリだけでなく、iPadアプリも見ることができます。
それにしてもパズドラすごいですね。さすが1300万ダウンロード。

元になるデータはapple公式のiTunes Store RSS
これをgoogle apps engine上でかいたpythonで一日一回cronで取得しています。

今回のアプリでは日本のメディアタイプがiTune Appsのデータを取得していますが、プルダウンの選択を変えればmusicとかも取得出来ます。




2013年4月21日日曜日

機械との競争

第1章 テクノロジーが雇用と経済に与える影響
第2章 チェス盤の残り半分にさしかかった技術と人間
第3章 創造的破壊ー加速するテクノロジー、消えてゆく仕事
第4章 では、どうすればいいか
第5章 結論ーデジタルフロンティア



コンピュータのが進化するにつれて、人間に任せるまでもない仕事が増えてきた。

例えば、ここ20年くらいで秘書の仕事が激減したということはよく報じられている。他にも事務仕事は減り続けているだろうし、今後も減少の一途を辿ることももはや常識だろう。

コンピュータの処理速度は日進月歩で向上し、価格の下落も激しい。そのような中、もはや人間が勝負を挑み続けても勝ち目は到底ない。

そこで、勝ち目のない競争(race against machine)を挑むのではなく、上手く利用してやろう(race with machine)、というのが本書の提案となる。

計算能力などでは無類の強さを誇るコンピュータも新しいアイデアを出したり人とのコミュニケーションを必要とする分野ではまだまだ人類を伍する事ができない。コンピュータの演算能力を存分に利用し、価値のあるサービスを提供することが必要となる。


ちょうど、最近、電王戦というコンピュータと人間の将棋の大会が行われた。結果はコンピュータの勝利ということだが、これは単に一つのマイルストーンを確認したに過ぎない。仮に人間側が勝利していたとしても、数年以内には確実に負ける宿命だっただろう。

競技としての将棋は、ちょうどオリンピックの陸上競技のように人間同士の純粋な健闘をたたえ楽しむ形で意義が存続できるという主張も多いが、ビジネスという側面で考えると、またひとつ人間が磨いても金にならない技能が増えたことになる。


2013年3月17日日曜日

JavaでPageRankアルゴリズム

有名なgoogleのPageRankアルゴリズム。
今更ながらどうやって実装してるのか調べてみました。

評価の高いページに参照されてるページは評価が高いはず、の仮説に基づいているのは有名な話ですが、実際にこれをコードに落としこむロジックはなかなか綺麗で良くできているものだと感心してしまいました。

論文に書かれている再帰的な数式をどうプログラムで表現すべきか、的な話はこちらが詳しいので興味を持った方はご参照を。

リンク解析とか: 重要度尺度と von Neumann カーネル

2013年1月20日日曜日

Google Apps Scriptでのファイル入出力

何年か前まではSpread Sheet用のVBA程度しかなかったGoogle Apps Script。
この前ちょっと調べてたらGoogle Drive上にファイルを書き込んだり読み込んだりできるよになったました。

なのでAPIの調査がてらFile操作関連のサンプルコード書いてみました。
ソースはこちら。(github)

1. Plain Textファイルの読み込み

まずGoogle Drive上にあるファイルを読み込むスクリプト
function readPlainFileByName(){
  var files = DocsList.getFiles();
  for(var i = 0; i < files.length; i++){
    var fileName = files[i].getName();
    if(fileName == "sampleFile"){
      var contents = files[i].getContentAsString();
      Logger.log(contents);
    }
  }
}
sampleFileというファイル名のファイルを読み込んでいます。 

ファイル名をピンポイントで指定するメソッドはないようですが、ファイルの中身を全検索してヒットしたファイル一覧を取得するメソッドはあるようです。
function readPlainFileBySeach(){
  var files = DocsList.find('Hello World!');
  for(var i = 0; i < files.length; i++){

    /* Stringに変換できないFileTypeはgetContentAsStringでエラーになるため */
    if(files[i].getFileType() == DocsList.FileType.OTHER){
      var contents = files[i].getContentAsString();
      Logger.log(contents);
    }
  }
}

2. Plain Textファイルの書き込み

次にGoogle Drive上にファイルを作成して文字列を書き込むスクリプト
function writePlainFile(){
    outputFile = DocsList.createFile('sampleFile', ''); 
    outputFile.append('Hello World!');
}
sampleFileにHello Worldしています。

3. Google Doc形式(拡張子がgdoc)のファイルの読み込み

Google Doc形式のリッチテキストを操作するには専用のクラスが用意されている。
function readRichFile(){
  var doc = DocumentApp.openById('Google Docのid');
  var text = doc.getText();  
  Logger.log(text);

}

Google DocのIDはGoogle DriveからGoogle Docを開いた時のURLに表示されています
https://docs.google.com/document/d/[Google DocのID]/edit

4. Google Doc形式のファイルの書き込み


同様にリッチテキスト用のクラスを利用してファイル書き出し
function writeRichFile(){
  var doc = DocumentApp.create('sampleRichFile');
  doc.appendParagraph('Hello World!');
  doc.saveAndClose(); 
}

感想


Google Drive上のファイル操作ができるので、できることの幅は広がりそうですが、ファイル名がピンポイントで指定できなかったり、google doc形式のファイルを開くのにid指定だったりと使い勝手がいまいちなのが残念。

あとjavascriptということなので、plain text操作時に改行を出力するすべがないみたいです。試しに改行を含んだファイルを読み込んだところ、綺麗に除去されてjavascript上に渡って来ました。

改行使えないとさすがに見栄えが悪すぎて実用に耐えないので、このへんはFile.writeNewLine()とか専用のメソッドを用意して対応してほしいところですね。