Linuxでもc#を使っていろんな数列を書き出してみる

はじめに

こんにちは、野村です。

今回は、c#を使っていくつかの数列を書き出してみます。

c#というプログラム言語は、Visual Studioという統合開発環境で使って書くのが一般的。
でも、Visual StudioはWindowsでしか使えません。

Windows以外でC#を書くときは、MonoDevelopという統合開発環境を使います。
最近は、Visual Studio Codeというエディタで書くのかな?僕はまだ使ったことがない。

今回は、Vimで書きました。
入力補完がないと結構面倒。もうVimでc#を書くことはないと思う。

あと、この機会にLINQを勉強しながら書いてみました。
少しわかってくると結構面白い。

インストールと実行

Windows以外でC#をビルドするときは、Monoを使います。
Monoというのは、.NET Framework互換の環境を実現するためのオープンソースのソフトウェア群です。

Monoのインストール

管理ユーザになって、mono-develをインストールします(debianの場合)。

# apt install mono-devel

実行

ソースファイルをVimで開いてコマンドモードから以下のコマンドを実行します。

:!mcs % -out:a.exe; ./a.exe

オプション「-out:」で書き出すファイル名を指定できる。

素数

・1より大きい自然数で、正の約数が1と自分自身のみである数。

using System;
using System.Collections.Generic;
using System.Linq;

class Program{
  private static IEnumerable<int> Sosu(IEnumerable<int> a){
    int m = a.Min();
    if (m > Math.Sqrt(a.Max())) return a;
    return a.Take(1).Concat(Sosu(a.Where(x=>x%m!=0)));
  }

  static void Main(){
    var a = Enumerable.Range(2,100-2); // 100未満の素数を表示
    Console.WriteLine(string.Join(",", Sosu(a)));
  }
}
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97

双子素数

・双子素数:差が2である2つの素数の組
・いとこ素数:差が4である2つの素数の組
・セクシー素数:差が6である2つの素数の組

using System;
using System.Collections.Generic;
using System.Linq;

class Program{
  private static List<int> Loop(List<int> a, int i, int f){
    if (a.Where(v=>v<=Math.Sqrt(i)).All(v=>i%v!=0)){
      a.Add(i);
      if (a.Any(v=>v==i-f)) return a;
    }
    return Loop(a,i+1,f);
  }

  private static void Twin(int f, int c){
    var b = Enumerable.Range(0,c);
    List<List<int>> m = new List<List<int>> ();
    m.Add(new List<int>(new int[] {2}));
    m.Add(new List<int>(new int[] {}));
    var r = b.Aggregate(m, (x,y)=>{
      List<int> z = Loop(x[0],x[0].Last()+1,f);
      x[0] = z;
      x[1].Add(z.Last());
      return x;
    });
    Disp(r[1],f);
  }

  private static void Disp(List<int> a, int f){
    var m = a.Select(v=>$"({v-f},{v})");
    Console.WriteLine(string.Join(",",m));
  }

  static void Main(){
    Twin(2,10); // 双子素数を10組表示
    Twin(4,10); // いとこ素数を10組表示
    Twin(6,10); // セクシー素数を10組表示
  }
}
(3,5),(5,7),(11,13),(17,19),(29,31),(41,43),(59,61),(71,73),(101,103),(107,109)
(3,7),(7,11),(13,17),(19,23),(37,41),(43,47),(67,71),(79,83),(97,101),(103,107)
(5,11),(7,13),(11,17),(13,19),(17,23),(23,29),(31,37),(37,43),(41,47),(47,53)

幸運数

・ポーランドの数学者スタニスワフ・ウラムによって提案された数列。
・素数の性質を研究するために、素数に似たルールで導き出せる数列を考案したとのこと。

using System;
using System.Collections.Generic;
using System.Linq;

class Program{
  private static List<int> z = new List<int>(){0};

  private static List<int> Luc(List<int> a, int i){
    var b = z.Concat(a).ToList();
    int s = b[i];
    int l = b.Count;
    if (s<=l) {
      var m = Enumerable.Range(0,l);
      var c = m.Where(v=>v%s!=0).Select(v=>b[v]).ToList();
      return Luc(c,i+1);
    }
    return a;
  }

  static void Main(){
    // 100未満の幸運数を表示
    var a = Enumerable.Range(0,100).Where(v=>v%2!=0).ToList();
    Console.WriteLine(string.Join(",", Luc(a,2)));
  }
}
1,3,7,9,13,15,21,25,31,33,37,43,49,51,63,67,69,73,75,79,87,93,99

階乗

・1 から n までのすべての整数の積。

using System;
using System.Linq;

class Program{
  private static int Fact(int a){
    if (a==0) return 1;
    var b = Enumerable.Range(1,a);
    return b.Aggregate((x,y)=>x*y);
  }

  static void Main(){
    var a = Enumerable.Range(0,10); // 階乗を10個表示
    Console.WriteLine(string.Join(",", a.Select(v=>Fact(v))));
  }
}
1,1,2,6,24,120,720,5040,40320,362880

フィボナッチ数

・フィボナッチ数:イタリアの数学者レオナルド・フィボナッチにちなんで名付けられた数
・リュカ数:フランスの数学者エドゥアール・リュカにちなんで名付けられた数

using System;
using System.Linq;

class Program{
  private static int Fibo(int a, int b, int c){
    if (c==0) return a;
    if (c==1) return b;
    return Fibo(a,b,c-2)+Fibo(a,b,c-1);
  }

  static void Main(){
    var a = Enumerable.Range(0,10);
    // フィボナッチ数を10個表示
    Console.WriteLine(string.Join(",", a.Select(v=>Fibo(0,1,v))));
    // リュカ数を10個表示
    Console.WriteLine(string.Join(",", a.Select(v=>Fibo(2,1,v))));
  }
}
0,1,1,2,3,5,8,13,21,34
2,1,3,4,7,11,18,29,47,76

パスカルの三角形

・二項展開における係数を三角形状に並べたもの。

using System;
using System.Collections.Generic;
using System.Linq;

class Program{
  private static IEnumerable<int> Pas(int a){
    if (a==0) return Enumerable.Range(1,1);
    var z = Enumerable.Range(0,1);
    var b = Pas(a-1);
    return z.Concat(b).Zip(b.Concat(z), (x,y)=>x+y);
  }

  static void Main(){
    var a = Enumerable.Range(0,10); // パスカルの三角形を10段表示
    foreach(int i in a){
      Console.WriteLine(string.Join(",", Pas(i)));
    }
  }
}
1
1,1
1,2,1
1,3,3,1
1,4,6,4,1
1,5,10,10,5,1
1,6,15,20,15,6,1
1,7,21,35,35,21,7,1
1,8,28,56,70,56,28,8,1
1,9,36,84,126,126,84,36,9,1

終わりに

以上、C#を使っていくつかの数列を書き出してみました。

LINQについては、以下の書籍を参考にしました。

LINQとは何なのか?何ができるのか?などについて気になっている人におすすめです。
とにかく語り口が面白い。
にもかかわらずしっかりと説明してくれているという、絶妙なバランスの上に成り立っている良書です。

というわけで、今回はこれにて。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

野村 野村のプロフィール
メインPCはWindows10のVirtualBox上のFreeBSD。Linux/Unixの小ネタを求めて日々右往左往してたりする。