//tips
//基本情報理解及びC#振り返り
ヒープソートとは、与えられたデータ列を大小などの順序通りになるよう並べ替える整列アルゴリズムで、ヒープ構造と呼ばれる二分木の一種を構築して並べ替えを行うもの。
ヒープとは、データ構造の一種で、木構造のうち、親要素が子要素より常に大きい(あるいは小さい)という条件を満たすもの。
コンピュータプログラムが利用するメモリ領域の種類の一つで、実行時に任意のタイミングで確保や解放が可能なものをヒープ領域という。
よく出てくる木構造はメモリの構造と理解できる。
参考:
https://products.sint.co.jp/topsic/blog/algorithm-type
https://medium.com/@yasufumy/data-structure-heap-ecfd0989e5be
シェルソートは、飛び飛びの列を繰り返しソートして、配列を大まかに整列された状態に近づけていく挿入ソートの改良版。
ハフマン符号化とは、データ中の文字列の出現頻度を求め、多く出現する文字列に短い符号を、まれに出現する文字列に長い符号を割り当てることで全データ量を縮小する。 JPEGやZIPなどで使用される方法。
コンピュータを0,1で管理するわかりやすい説明があったので下記紹介。
コンピューター内の回路には電気が流れており、この電気の流れをコントロールすることでコンピューターは計算をしている。
回路内は「電気が流れている状態(ON)」と「電気がながれていない状態(OFF)」の2つの状態しかない。
電流には、誤差が発生するため、その分を吸収するために、電圧が「0V~5V」までなら「電気がながれていない状態(OFF)」、「6V~10V」までなら「電気が流れている状態(ON)」などと定義し、正しく「ON」「OFF」を切り替えることができるようにしている。
この「ON」「OFF」を「1」と「0」に対応させてやることですべての情報を操作する。
参考:
http://www.snap-tck.com/room03/c02/comp/comp032.html
プログラムカウンタとは、マイクロプロセッサ(MPU/CPU)内部でデータを保持するレジスタの一種で、次に実行すべき命令が格納されているメモリ上の番地(アドレス)を保存しているもの。
そもそも、CPUは主記憶メモリに格納されている情報を読み出し、処理して返すもので、処理がメインとなっているため、記憶があまり得意ではなく、記憶に関してはCPUのレジスタという単位で、細かくメモリからの受け取り情報を管理している。
このレジスタ経由でメモリからの情報を受け取り、ALU(演算装置)で演算し、結果をまたレジスタに書き戻し、それがメモリに引き渡されて処理が完了となる。
参考:
https://itmanabi.com/cpu-order/
//C#
店舗売上を求めるために店舗名をDictionaryクラスのキーとして、対応する売上高を値に加算していく。
public Dictionary<string,int>GetPerStoreSales()
{
Dictionary<string,int> dict=new Dictionary<string,int>();
foreach(Sale sale in _sales)
{
if(dict.ContainsKey(sale.ShopName))
{
dict[sale.ShopName] += sale.Amount;
}
else
{
dict[sale.ShopName]=sale.Amount;
}
return dict;
}
}
ContainsKeyメソッドで指定したShopNameがdict内に格納されているかを調べる。
格納されていなければ次の行で最初の売上高をdictに格納する。
これをmainメソッドに反映させると、
static void Main(string[] args)
{
SalesCounter sales = new SalesCounter(ReadSales(“sales.csv”));
Dictionary<string,int> amountPerStore=sales.GetPerStoreSales();
foreach(KeyValuePair<string,int> obj in amountPerStore)
{
Console.WriteLine(“{0} {1}”,obj.Key,obj.Value);
}
}
Visual studioでソリューションをクリックし、新しいプロジェクトを追加作成すると、新規のnamespaceのフォルダが作られる。
CsvファイルをSalesCalculatorフォルダの下に格納することできちんと読み込みが行われた。
完成したプログラムに対してインターフェースを導入してみる。ここはunityではあまり使わなかった部分。
定義などで見かけるIListやICollectionのIはインターフェースが定義しているメソッドやプロパティを実装していることを示す。
例の見る方がわかりやすいので下記に示す。
List<int> list =new List<int>(){1,2,3,4,5};
List<Tは>、ICollection<T>のインターフェイスを持っているのでICollection型の変数に代入できる。
ICollection<T> collection=list;
collectionはICollection型なのでCountプロパティを使える。
var count= collection.Count;
collectionはICollection型なのでAddメソッドを使える。
Collection.Add(6);
このように一つの型が含む定義により様々な派生形を作成する事ができる。これがインターフェースのよさとなる。
メソッドの戻り値や引数にインターフェースを指定するとプログラムの修正への対応範囲が広くなる。
例えば、List<Sale>からprivate IEnumerable<Sale> _sales;に変更するだけで、 IEnumerableが対応できるリストだけでなく、配列までも対応できるようになる。List<Sale>としていたらList型のものしか対応できなかったので扱える範囲が広がることになる。
List<Sale>型ではなく、それらを含むIEnumerable<Sale>に対してコードを書いている。
具体的なクラスではなく、それらを含むインターフェースに対してプログラミングをすることで扱える幅が広くなることを覚えておく。
最後にvarで冗長な型の定義部分を減らしていく。
最終形態を下記に記載。
<Main>
using System;
using System.Collections.Generic;
using System.IO;
namespace SalesCalculator
{
class Program
{
static void Main(string[] args)
{
var sales = new SalesCounter("sales.csv");
var amountPerStore = sales.GetPerStoreSales();
foreach (var obj in amountPerStore)
{
Console.WriteLine("{0} {1}",obj.Key,obj.Value);
}
}
}
}
<売上クラス>
using System;
namespace SalesCalculator
{
public class Sale//売上クラス
{
public string ShopName { get; set; }
public string ProductCategory { get; set; }
public int Amount { get; set; }
}
}
<売上集計クラス>
using System;
using System.Collections.Generic;
using System.IO;
namespace SalesCalculator
{
public class SalesCounter//売上集計クラス
{
private IEnumerable<Sale> _sales;
public SalesCounter(string filePath)//コンストラクタ
{
_sales = ReadSales(filePath);
}
public IDictionary<string, int> GetPerStoreSales()
{
var dict = new Dictionary<string, int>();
foreach (var sale in _sales)
{
if (dict.ContainsKey(sale.ShopName))
{
dict[sale.ShopName] += sale.Amount;
}
else
{
dict[sale.ShopName] = sale.Amount;
}
}
return dict;
}
private static IEnumerable<Sale> ReadSales(string filePath)
{
List<Sale> sales = new List<Sale>();
string[] lines = File.ReadAllLines(filePath);
foreach (string line in lines)
{
string[] items = line.Split(',');
Sale sale = new Sale
{
ShopName = items[0],
ProductCategory = items[1],
Amount = int.Parse(items[2])
};
sales.Add(sale);
}
return sales;
}
}
}
次はラムダ式・LINQの導入も含めたものを考えていく。
その前に独特な用語の確認。
走査とは、先頭から順に見ていく,という意味で、スキャン(scan)と同じ意味。
射影とは、データベース関連の話で出てくる用語のひとつで、テーブルから特定の列のデータのみを取り出すこと。
シーケンスとは、標準クエリ演算子(Whereなど)の操作対象データのこと。配列やList<T>もシーケンスの一つで、IEnumerable<T>インターフェースを実装するオブジェクトは全てシーケンス。