2017年01月15日

TypeScriptでProject Euler #3 「最大の素因数」


第3問目は素因数分解の問題です。

13195 の素因数は 5, 7, 13, 29 である.

600851475143 の素因数のうち最大のものを求めよ.

   Project Euler日本語翻訳サイト から引用


ポラード・ロー素因数分解法

せっかくなので、少し前にC#で書いた「ポラード・ロー素因数分解法」をTypeScriptに移植しようと思います。

事前に、最大公約数をもとめるGcd関数と、素数判定の関数 IsPrime を定義します。この2つのメソッドは、Utilsクラスに入れ、前回と同様、mathフォルダに保存します。ファイル名は、mathUtils.tsです。

export class Utils {
    static gcd(a: number, b: number): number {
        if (a < b)
            return this.gcd(b, a);  // 引数を入替えて自分を呼び出す
        if (b === 0)
            return a;
        let d = 0;
        do {
            d = a % b;
            a = b;
            b = d;
        } while (d !== 0);
        return a;
    }

    static isPrime(num: number): boolean {
        let boundary = Math.floor(Math.sqrt(num));
        if (num === 1)
            return false;
        if (num === 2)
            return true;
        for (let i = 2; i <= boundary; ++i) {
            if (num % i === 0)
                return false;
        }
        return true;
    }
}

これを使い、「ポラード・ロー素因数分解法」を使った素因数分解クラスを定義します。C#のコードをTypeScriptに移植しただけなので、それほど苦労なく書けました。

import { Utils } from './mathUtils';

export class PrimeFactor {
    public *enumerate(n: number): IterableIterator<number> {
        while (n > 1) {
            let factor = this.getFactor(n);
            yield factor;
            n = n / factor;
        }
    }

    private getFactor(n: number, seed: number = 1): number {
        if (n % 2 === 0)
            return 2;
        if (Utils.isPrime(n))
            return n;
        let x = 2;
        let y = 2;
        let d = 1;
        let count = 0;
        while (d === 1) {
            count++;
            x = this.f(x, n, seed);
            y = this.f(this.f(y, n, seed), n, seed);
            d = Utils.gcd(Math.abs(x - y), n);
        }
        if (d === n)
            // 見つからなかった、乱数発生のシードを変えて再挑戦。
            return this.getFactor(n, seed + 1);
        // 素数でない可能性もあるので、再度呼び出す
        return this.getFactor(d);
    }

    private seeds: number[] = [3, 5, 7, 11, 13, 17];
    private f(x: number, n: number, seed: number): number {
        return (this.seeds[seed % 6] * x + seed) % n;
    }
}

このクラスを PrimeFactor.ts としてmathフォルダに保存します。

getFactorメソッドの引数には、省略時の値を指定しました。これはC#と同じですね。

TypeScript書いていて、いつも間違えるのは、比較演算子 === を == と書いてしまうこと。慣れるしかないですね。


最大の素因数を求める

さて、素因数分解はできましたので、これで問題を解くことができます。最大の素因数を求めればいいんですね。

ところで、「ポラード・ロー素因数分解法」って因数を小さい順に列挙してくれるのかな? たぶん小さい順位列挙してくれると思います。ということで最後の素因数が最大の素因数ということになります。LINQ使えれば、Lastメソッドで一発なんですがね。

しかたない、for文で回すことにしましょう。もっと賢いやり方があるような気もしますが...

import * as Utils from './utils';
import Stopwatch = Utils.Stopwatch;
import { PrimeFactor } from './math/PrimeFactor';

class Solver {
    exec(num: number): number {
        let pf = new PrimeFactor();
        let last;
        for (let n of pf.enumerate(num)) {
            last = n;
        }
        return last;
    }
}

class Application {
    static run(): void {
        let sw = Stopwatch.startNew();
        try {
            let p = new Solver();
            let n = p.exec(600851475143);
            console.log(n);
        } finally {
            sw.stop();
            console.log(sw.toString());
        }
    }
}

Application.run();

これで、完成です。 正しく動いているようです。

ところで、C#に慣れていると、ついつい大文字で始まるファイル名にしたくなりますが。 TypeScriptの場合、ファイル名は小文字で始めるのが慣習なのかな?
 


※Stopwatchクラスについては、「TypeScriptでProject Euler #0」 を見てください。

  

Posted by gushwell at 22:00Comments(0)TrackBack(0)TypeScript

2017年01月12日

TypeScriptでProject Euler #2 「偶数のフィボナッチ数」


TypeScriptでProject Eulerに挑戦する第2問目です。
第1回目から随分と間が空いてしまいましたが、気にせずマイペースで進めます。 

問題

フィボナッチ数列の項は前の2つの項の和である. 最初の2項を 1, 2 とすれば, 最初の10項は以下の通りである.

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

数列の項の値が400万以下の, 偶数値の項の総和を求めよ.

   Project Euler日本語翻訳サイト から引用
 

フィボナッチ数列を求める関数を定義

まずは、以下のようなクラスを定義して、fibonacci.ts として保存。mathフォルダを作成し、そこに保存します。

export class Fibonacci {
    static enumerate(first: number, second: number, callback: (n: number) => boolean): void {
        if (callback(first) === false)
            return;
        if (callback(second) === false)
            return;
        while (true) {
            let fibo = first + second;
            first = second;
            second = fibo;
            if (callback(fibo) === false)
                return;
        }
    }
}

配列に入れて返すことも考えたけど、今回はパス。 yield 構文が使えるみたいだけど、まだよくわかっていないので、コールバック関数を使うことにします。

コールバック関数の引数として、求めたフィボナッチ数が渡ります。 コールバック関数では、戻り値として true を返せば列挙を継続し、falseを返せば列挙を終了します。

こうすれば、フィボナッチ数列を求めるロジックと、問題特有の条件部の記述をきれいに分けることができます。

完成させる

Fibonacci.tsは、mathフォルダにあるので、そこを指すようにしてimpoortします。

つぎのようにすると、exportされたFibonacciクラスがその名前のまま利用できます。

import { Fibonacci } from './math/Fibonacci';

Fibonacciクラスを使って、solveメソッドを以下のように書きます。 コールバック関数の中で、偶数のフィボナッチ数だけを加算するようにしています。

import * as Utils from './utils';
import Stopwatch = Utils.Stopwatch;
import { Fibonacci } from './math/Fibonacci';

class Solver {
    public exec(maxnum: number): number {
        let sum = 0;
        Fibonacci.enumerate(1, 2, (n) => {
            if (n >= maxnum)
                return false;
            if (n % 2 === 0)
                sum += n;
            return true;
        });
        return sum;
    }
}

class Application {
    static run(): void {
        let sw = Stopwatch.startNew();
        try {
            let p = new Solver();
            let n = p.exec(4000000);
            console.log(n);
        } finally {
            sw.stop();
            console.log(sw.toString());
        }
    }
}

Application.run();

ファイルを小分けにすると、いちいち、import 書かないといけないのが面倒ですね。 なにか良い方法がないのかなー。

とりあえず、実行して動くことが確認できました。
 

やっぱり yield使いたい

でもやっぱり yield使いたいです。ということで、yield使って書き直してみました。 さっきと、メソッド名変えてます。

export class Fibonacci {
    static * generate(first: number, second: number): IterableIterator<number> { 
        yield first; 
        yield second;
        while (true) {
            let fibo = first + second;
            first = second;
            second = fibo;
            yield fibo;
        }
    }
}

まだ良くわかってないけど、メソッド名の前に * を付けないといけないみたいです。戻り値を IterableIterator<number> にしてるんだから、それだけでいいんじゃね、という気がするけど、まあそういう文法なので従うしかないです。TypeScriptでは、この * の付いているメソッド/関数を Generatorと呼ぶらしいです。

Fibonacci.generateを呼び出す側の ProjectEuler.ts は以下のようになります。
 

import * as Utils from './utils';
const Stopwatch = Utils.Stopwatch;
import { Fibonacci } from './math/Fibonacci';

class Solver {
    public exec(maxnum: number): number {
        let sum = 0;
        for (let n of Fibonacci.generate(1, 2)) {
            if (n >= maxnum)
                break;
            if (n % 2 === 0)
                sum += n;
        }
        return sum;
    }
}

class Application {
    static run(): void {
        let sw = Stopwatch.startNew();
        try {
            let p = new Solver();
            let n = p.exec(4000000);
            console.log(n);
        } finally {
            sw.stop();
            console.log(sw.toString());
        }
    }
}

Application.run();


for 文が使えるので、随分と読みやすくなったと思います。 やっぱり、今どきの言語は、yield使えないとね。

でも、for..in と for..of で動きが違うってどうなの? 間違いやすいですね。 英語圏の人は、inとofのニュアンスから違いを類推できるのかな?

 

※Stopwatchクラスについては、「TypeScriptでProject Euler #0」 を見てください。

  
Posted by gushwell at 22:10Comments(0)TrackBack(0)TypeScript

2016年12月15日

TypeScriptでProject Euler #1 「3と5の倍数」


今回から、実際にProject Eulerの問題をTypeScriptで解いていきます。


問題

第1問は、

1000 未満の 3 か 5 の倍数になっている数字の合計を求めよ.

   Project Euler日本語翻訳サイト から引用

というもの。

この問題は、第1問目ということで簡単ですね。


TypeScriptで問題を解く

TypeScriptでProject Euler #0で作成したテンプレートプログラムをフォルダーごとコピーし、新しいプロジェクトを作成し、Solverクラスのexecメソッドを問題に合わせて書き換えます。

作成したTypeScriptのコードは以下の通り。

import * as Utils from './utils';
import Stopwatch = Utils.Stopwatch;

class Solver {
    exec(num: number): number {
        var sum = 0;
        for (var i = 1; i < num; i++) {
            if (i % 3 === 0 || i % 5 === 0)
                sum += i;
        }
        return sum;
    }
}
class Application {
    static run(): void {
        let sw = Stopwatch.startNew();
        try {
            let p = new Solver();
            let n = p.exec(1000);
            console.log(n);
        } finally {
            sw.stop();
            console.log(sw.toString());
        }
    }
}
Application.run();

※Stopwatchクラスについては、「TypeScriptでProject Euler #0」 を見てください。


プログラムを書き終えて

今回のプログラムでは、新たに得たTypeScriptの知識というはほとんどないかな。

TypeScript は、この程度のプログラムだと、C#と同じ感覚で書けますね。僕の中では、比較演算子が === と3つつなげるのが一番の大きな違いといった感じです。

そういえば、execメソッドで、var 使っちゃいましたが、スコープの扱いがC#に近い let を使ったほうがいいですね。次回からは、let使おうと思います。

ちなみに、僕のMacBookAirでは、デバッグコンソールで20ミリ程度で終わるので、この程度のプログラムならば自分にとって分かりやすいコードで書けばいいかなと思います。LINQ使えれば、もっと簡単に書けるんですけどね。まあ仕方ないですね。


答えは皆さんの楽しみのために載せないでおきますね。

解いた答えがあっているかは、本家サイトでアカウント登録して、該当する問題のページを開くと、答えを入力する欄があり、ここに解いた値を入れcheck ボタンを押すことで、答え合わせができるようになっています。

  
Posted by gushwell at 21:30Comments(0)TrackBack(0)TypeScript

2016年12月13日

TypeScriptでProject Euler #0 はじめに


これまで、初めてのTypeScript(1),(2),(3),(4),(5),(6), と書いてきましたが、今回から記事のタイトルを変更します。

Project Euler とは

Project Eulerとは、数学的問題をひたすらプログラムで解いていくというサイトです。 現時点で500以上もの問題が掲載されています。

問題を日本語に訳してあるサイトもあります。 有志の方々が、日本語に訳して下さっているので、とてもありがたいです。

今回使うプログラミング言語は、C#ではなくTypeScript。Visual Studio Code + node.js の環境で動かします。

TypeScriptってどんな言語かを知るのが目的なので、それほど多くの問題を解くことはしないと思いますが、10問程度は解きたいと思います。

僕の貧弱な数学の知識では、そもそもそんなに多くの問題を解けるとは思いませんので、10問くらいがちょうどよいでしょう。

方針

なお、以下のような方針で臨みたいと思います。

速度にも気を配ったコードとする (時間を計測する)

すべての問題は、1分以内で解ける問題だということです。Project Eulerが開始されたのは、2001年ということですから、初期に出題された問題ならば、今のPCで最悪でも数秒程度で答えが求められるっていうことだと思います。 なので目標は10秒以内。速度にも気を配ったコードにしたいと思っています。

再利用可能なものはクラスとして独立させておく。

後で使えそうなロジックは、別クラスとして定義することとします。 これによって、一時的には、記述するコード量が増えてしまいますが、長い目でみれば、メリットがあると思います。

すべての問題に対して、Solverクラスのexecメソッドを実装する。

後述のひな形コードのように、たとえ冗長になったとしても、問題を解くコードは、Solver クラスの exec静的メソッド あるいは インスタンスメソッドとして実装することとします。 もちろん、execメソッドの引数は、その問題ごとに変化します。

なお、複数のやり方で問題を解いた場合は、SolverB、SolverC というクラスを定義し、そこに同じ引数のexecメソッドを実装します。

外部のライブラリは使わないことにする。

これはやってみたいとわからない部分もありますが、基本は、TypeScriptが持つ基本的な機能だけで問題を解きます。

ひな形コード

実は、前回の記事の「初めてのTypeScript (6)」で示したプログラムが、そのひな形コードになってます。 再度示しますね。

まずは、app.tsを示します。execメソッドの部分は、問題ごとに実装が異なるので、ひな形では、引数で得た値を返すだけのコードとしています。

import { Utils } from './utils';
import Stopwatch = Utils.Stopwatch;

class Solver {
    exec(maxnum: number): number {
        return maxnum;
    }
}

class Application {
    static run(): void {
        let sw = Stopwatch.startNew();
        try {
            let p = new Solver();
            let n = p.exec(100000);
            console.log(n);
        } finally {
            sw.stop();
            console.log(sw.toString());
        }
    }
}

Application.run();

次は、utils.ts。

export class Stopwatch {
    private startTime: number;
    private stopTime: number;
    static startNew(): Stopwatch {
        let sw = new Stopwatch();
        sw.start();
        return sw;
    }
    start() {
        this.startTime = Date.now();
    }
    stop() {
        this.stopTime = Date.now();
    }
    elapsed(): number {
        return this.stopTime - this.startTime;
    }
    toString(): string {
        let tms = this.elapsed();
        let h = Math.floor(tms / (1000 * 60 * 60));
        let m = Math.floor(tms / (1000 * 60));
        let s = Math.floor(tms / 1000);
        let ms = Math.floor(tms % 1000);
        return `${this._zeroPadding(h)}:${this._zeroPadding(m)}:${this._zeroPadding(s)}:${this._zeroPadding(ms, 3)}`;
    }
    private _zeroPadding(n: number, d: number = 2): string {
        let zero = '';
        for (let i = 1; i < d; i++)
            zero += '0';
        return (zero + n).slice(-d);
    }
}

このutils.tsは、これから解くすべての問題で利用します。必要ならばここにクラスを追加していくかもしれません。

これで、動くはずですので、F5キーを押して、正しく動作することを確認します。

tsconfig.json, tasks.json, launch.json

説明は省略しますが、Visual Studio Codeの設定ファイルである tsconfig.json, tasks.json, launch.json も載せておきます。
 

■tsconfig.json

{
    "compilerOptions": {
        "target": "es6", 
        "module": "commonjs",
        "sourceMap": true
    }
}

■.vscode/tasks.json

{
  "version": "0.1.0",
  "command": "tsc",
  "isShellCommand": true,
  "args": ["-p", "."],
  "showOutput":"always",
  "problemMatcher": "$tsc"
}

■.vscode/launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "起動",
      "type": "node",
      "request": "launch",
      "program": "${workspaceRoot}/ProjectEuler.js",
      "stopOnEntry": false,
      "args": [],
      "cwd": "${workspaceRoot}",
      "preLaunchTask": null,
      "runtimeExecutable": null,
      "runtimeArgs": [
        "--nolazy"
      ],
      "env": {
        "NODE_ENV": "development"
      },
      "console":"internalConsole",
      "sourceMaps": false,
      "outDir": null
    },
    {
      "name": "アタッチ",
      "type": "node",
      "request": "attach",
      "port": 5858,
      "address": "localhost",
      "restart": false,
      "sourceMaps": false,
      "outDir": null,
      "localRoot": "${workspaceRoot}",
      "remoteRoot": null
    },
    {
      "name": "プロセスにアタッチ",
      "type": "node",
      "request": "attach",
      "processId": "${command.PickProcess}",
      "port": 5858,
      "sourceMaps": false,
      "outDir": null
    }
  ]
}

次回は、これらのファイル(.ts, .json)があるフォルダーをコピーして利用します。


次のエントリーからは、実際に問題を解いていきます。

ただし、コードは載せますが、答えそのものは載せません。それは皆さんの楽しみのために取っておきましょう。

  
Posted by gushwell at 22:10Comments(0)TrackBack(0)TypeScript

2016年12月11日

初めてのTypeScript (6) - モジュールのimport/export


これは TypeScript Advent Calendar 2016 の11日目の記事です。 


初めてのTypeScript (4) - classをし別ファイルから利用してみる」で挫折したexport/importに再挑戦します。

今度は、前回構築したVisual Studio Code+TypeScriptの環境を使います(mode.jsを使っている)ので、ブラウザのような制限は受けないはずです。

tsconfig.json, tasks.json, launch.jsonは、基本的にそのまま利用したいので、TypeScriptのソースファイルが入っているフォルダごとコピーして、新しいプロジェクトとします。

TypeScriptのnamespaceは使わない

いろいろ試行錯誤した結果ですが、「TypeScriptでnamespaceは使わない」が現時点での僕の結論です。

C#プログラマーからすると、「なんで?」と思うのですが、モジュールの概念が微妙に違うので、TypeScriptにおいては、namespaceは意味がないという結論にたどり着きました。

それと、詳細は割愛しますが、C#の感覚で複数のファイルに同じnamespace名を付けると、importする側では、名前が重複した状態になりビルドできません。 無理やりビルドエラーを取ろうと頑張ると、何のためのnamespaceかが全く分からないカオス状態になります。

ブラウザ環境でもたぶん同じ状況になるのだと思います(すいません、これは確かめていません)。

モジュールのexport

では、「初めてのTypeScript (4)」と同じように、Utils.tsファイルを定義します。

    export class Stopwatch {
        private startTime: number;
        private stopTime: number;

        static startNew(): Stopwatch {
            let sw = new Stopwatch();
            sw.start();
            return sw;
        }

        start() {
            this.startTime = Date.now();
        }

        stop() {
            this.stopTime = Date.now();
        }

        elapsed(): number {
            return this.stopTime - this.startTime;
        }

        toString(): string {
            let tms = this.elapsed();
            let h = Math.floor(tms / (1000 * 60 * 60));
            let m = Math.floor(tms / (1000 * 60));
            let s = Math.floor(tms / 1000);
            let ms = Math.floor(tms % 1000);
            return `${this._zeroPadding(h)}:${this._zeroPadding(m)}:${this._zeroPadding(s)}:${this._zeroPadding(ms, 3)}`;
        }

        private _zeroPadding(n: number, d: number = 2): string {
            let zero = '';
            for (let i = 1; i < d; i++)
                zero += '0';
            return (zero + n).slice(-d);
        }
    }

これを utils.ts というファイル名で保存します。

モジュールのimport

では、このutils.tsをimportしてみます。

import * as Utils from './utils';

こうすると、同一フォルダにある utils.tsをimportしてくれます。

これで、

let sw = Utils.Stopwatch.startNew();

のような記述が可能になります。

Stopwatchの前のUtils.を省略したいならば、

import * as Utils from './utils';
import Stopwatch = Utils.Stopwatch;

のような書けばよいみたいです。ちなみに、最後の行は、次のコードと基本的には同じ意味だと考えてもらって差し支えないかなと思います。

const Stopwatch = Utils.Stopwatch;

メインプログラムを書く

utils.tsに定義してあるクラスを利用するコードを書いてみました。

import * as Utils from './utils';

class Solver {
    exec(maxnum: number): number {
        return maxnum;
    }
}

class Application {
    static run(): void {
        let sw = Utils.Stopwatch.startNew();
        try {
            let p = new Solver();
            let n = p.exec(100000);
            console.log(n);
        } finally {
            sw.stop();
            console.log(sw.toString());
        }
    }
}

Application.run();

これを ProjectEuler.ts というファイルで保存します。

Shift+Command+Bでビルドします。

無事ビルドできました。

launch.json の書き換え。

一か所だけ、launch.json の書き換えが必要です。以下のように起動するプログラム名を変更します。

 "program": "${workspaceRoot}/ProjectEuler.js",

実行

F5キーで実行します。デバッグコンソールに以下のような出力がされ正しく動いていることが確認できました。

node --debug-brk=16838 --nolazy ProjectEuler.js 
Debugger listening on [::]:16838
100000
00:00:00:021

これから

ProjectEulerという名前でピンときた方もいると思いますが、実は、今まで書いてきた記事は、TypeScriptを使ってProject Eulerの問題を解くための準備みたいなものです。

今回示したコードは、TypeScriptを使ってProjectEulerの問題を解くためのひな型コードとなっています。最初は、ブラウザで動作するプログラムでコードを書こうと考えていたのですが、途中方向転換し、Node.js上で動かすこととにしました。

TypeScriptを学習するために題材としてProject Eulerを選んだので、10問程度を解ければよいかなと今は考えています。

ということで、次回からは、TypeScriptでProjectEulerに挑戦していこうと思っています。 といっても、あと少ししたら来年出版予定のC#の本の執筆作業のラストスパートで忙しい時期に突入してしまうので、どうなることやら...

  
Posted by gushwell at 21:43Comments(0)TrackBack(0)TypeScript

2016年12月09日

初めてのTypeScript (5) - Visual Studio Code(Mac)でTypeScript


これは TypeScript Advent Calendar 2016 の9日目の記事です。 


えー、前回までVisual Studio 2015を使っていたのですが、export/importでつまずいてしまってので、Visual Studio Code + node.jsの環境で、TypeScriptに再挑戦です。

今回は、Macを使っています。といっても、WindowsでもCommandキーをControlキーと読み替えてもらえれば、Windowsでもほとんどそのまま適用できる内容だと追います。

スクリーンショットを撮っていませんが、普通のプログラマーならば、文字だけでも大丈夫かと思います。


インストール

まずは、Visual Studio codeとnode.js をインストールします。この二つはダウンロードして、インストーラを起動するだけなので難しいことはありません。

それぞれのバージョンは以下のとおりです。

Visual Studio Code : 1.7.2
node.js : 6.9.1


次に、TypeScriptをインストールします。ターミナルを起動し、以下のコマンドを入力します。

npm install -g typescript

でも、このインストールで失敗してしまいました。メッセージを読むと、権限が不足しているらしいです。普通のMacのカジュアルユーザの僕には、Mac/Unixについて疎いので対処方法がよくわかりません。
調べたら、以下のようなコマンドを実行すれば良さげ。

sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}

再度、

npm install -g typescript

でインストール。今度は成功しました。TypeScriptのバージョンは、2.0.10 でした。
 

必要なプログラムのインストールが終わったので、Visual Studio Code(以下、VSCode)を起動します。


以降は、以下のページを参考にしながら、試しています。

https://code.visualstudio.com/Docs/languages/typescript


tsconfig.jsonの作成

TypeScriptのプログラムソースファイルを置く任意のフォルダーを開きます。

このフォルダに、tsconfig.jsonというファイルを作成し、以下のような内容を記述します。

{
    "compilerOptions": {
        "target": "ES5",
        "module": "commonjs",
        "sourceMap": true
    }
}


プログラムコードの入力

次に、同じフォルダーに、HelloWorld.ts ファイルを作成します。ここにTypeScriptのコードを書きます。

class Startup {
    public static main(): number {
        console.log('Hello World');
        return 0;
    }
}

Startup.main();


ビルドの構成

次に、Shift+Command+P を押し、コマンドパレットを出します。

Configure までタイプすると、候補が出てくるので「タスクランナーの構成」を選んで、Enterを押します。

すると、またドロップダウンの一覧が表示されますので、「TypeScript - tsconfig.json. 」を選びます。

これにより、以下にようなtasks.json ファイルが、 .vscodeフォルダーに作成されます。

{
     // See http://go.microsoft.com/fwlink/?LinkId=733558
     // for the documentation about the tasks.json format
     "version": "0.1.0",
     "command": "tsc",
     "isShellCommand": true,
     "args": ["-p", "."],
     "showOutput": "silent",
     "problemMatcher": "$tsc"
}


ビルドの実行

Shift+Command+B でビルドします。

問題がなければ、HelloWorld.tsのある同じフォルダに、HelloWorld.jsファイルが作成されます。


デバッグ環境の設定

いよいよ、デバッグです。Shift+Command+Dでデバッグペイン?を表示させます。

VSCodeのデバッグペインの左上に「デバッグ」というボタンがあるので、それをクリックします。
環境の選択の一覧の中から、「node.js」を選択します。
すると、以下のようなlaunch.jsonファイルが、.vscodeフォルダに作成されます。

{
    // Use IntelliSense to learn about possible Node.js debug attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "プログラムの起動",
            "program": "${workspaceRoot}/app.js",
            "cwd": "${workspaceRoot}",
            "outFiles": [],
            "sourceMaps": true
        },
        {
            "type": "node",
            "request": "attach",
            "name": "プロセスに添付",
            "port": 5858,
            "outFiles": [],
            "sourceMaps": true
        }
    ]
}

このファイルのapp.js を HelloWorld.js に書き換えて保存します。


デバッグの実行

再度、デバッグボタンを押します。F5キーを押してもデバッグを開始できます。

VSCodeの下に、デバッグコンソールに結果が表示されます。
デバッグコンソールが表示されない場合は、Shift+Command+Yで表示できます。
 

Visual Studio 2015と同様、ブレークポイントを設定してデバッグすることもできます。


-----

Visual Studio Codeは、Visual Studioと違って、All in One の環境ではないので、いちいち設定ファイルを自分で記述しないといけないのが面倒です。なんでもGUIで設定できるVisual Studioに慣れすぎた体にはちょっと辛いです。数十年前に戻ってしまったようなそんな感じです。あの頃は、環境設定も楽しい時間でしたが、今は面倒だなって思う気持ちのほうが勝ってます...

まあ、なんとか Visual Studio CodeでTypeScriptをビルド+デバッグする環境が整いました。




 

  
Posted by gushwell at 21:18Comments(0)TrackBack(0)TypeScript