17 Aralık 2018 Pazartesi

Kombinasyon

Formülü
n elemanlı kümenin r elemanı alt kümelerinin sayısını bulmak için formül şöyle
n! / r! (n - r) !
Aslında bu formül uzun. Dahada kolayı için
n * (n-1)... / r! yaparız.  Üst taraf r kadar eksilerek gider.

Örnek
Elimizde şöyle bir kod olsun
String[] operators = {"+", "-", "*"};
Tüm kobinasyonları bulmak için iç içe 3 döngü kurarız. Şöyle yaparız. Döngü kurmadan genel çözümleri için buraya bakınız.
for (int i=0; i < operators.length; ++i) {
  for (int j=0; j < operators.length; ++j) {
    for (int k=0; k < operators.length; ++k) {
      ...
    }
  }
}
Örnek
Elimizde şöyle bir dizi olsun.
[ 1, 2, 3, 4]
2,3 ve 4'lü kombinasyonlar şöyledir
[1] => [1]
[2] => [2]
[3] => [3]
[4] => [4]
[5] => [1, 2]
[6] => [1, 3]
[7] => [1, 4]
[8] => [2, 3]
[9] => [2, 4]
[10] => [3, 4]
[11] => [1, 2, 3]
[12] => [1, 2, 4]
[13] => [1, 3, 4]
[14] => [2, 3, 4]
[15] => [1, 2, 3, 4]
Örnek
C# ile şöyle yaparız.
public static IEnumerable<int[]> Combinations(int n, int k)
{
  var result = new int[k];
  var stack = new Stack<int>();
  stack.Push(0);

  while (stack.Count > 0) {
    int index = stack.Count - 1;
    int value = stack.Pop();

    while (value < n) {
      result[index++] = value++;
      stack.Push(value);

      if (index == k) {
        yield return result;
        break;
      }
    }
  }
}
6,2 yaparsak çıktı olarak şunu alırız
[0,1], [0,2], [0,3], [0,4], [0,5], [1,2], [1,3], [1,4], [1,5], [2,3], [2,4], [2,5], [3,4], [3,5], [4,5]

Kombinasyon Olasılık Problemlerinde Kullanılır
7 koltuklu bir sinemeda John ve Mary'nin yanyana oturmama olasılığı nedir sorusunu çözmek için kombinasyonla önce yanyana olan koltuk sayısını bulmak gerekir.

Ben bu yöntemi sevmiyorum. Daha kolay bir yöntem şöyle
John'un uca oturma ihtimali 2/7. Mary'nin yanına gelmeme ihtimali 5/6.
John'un ortaya oturma ihtimali 5/7. Mary'nin yanına gelmeme ihtimli 4/6.

Şöyle yaparız.

27⋅56+57⋅46=3042=57




14 Aralık 2018 Cuma

ESRI Formatı

Giriş
ESRI Shapefile, ArcGIS ve QGIS konularını bilmek gerekir.

1. ESRI Shapefile Nedir
Bir başka açıklama şöyle. Shape dosyasında bazen istenilenden daha fazla özellik bulunur. Bu özellikleri süzmek gerekebilir.
The ESRI Shapefile or simply a shapefile is a popular geospatial vector data format for geographic information systems software. It is developed and regulated by ESRI as a (mostly) open specification for data interoperability among ESRI and other software products. A "shapefile" commonly refers to a collection of files with ".shp", ".shx", ".dbf", and other extensions on a common prefix name (e.g., "lakes.*"). The actual shapefile relates specifically to files with the ".shp" extension, however this file alone is incomplete for distribution, as the other supporting files are required.
Bir örnek burada

.prj dosyası
Genellikle dosyala şöyle
mygovernment.shp
mygovernment.shx
mygovernment.dbf
mygovernment.prj
.prj dosyası kullanılan koordinat sistemini belirtiyor. Bir örnek burada

Her koordinat sistemi GIS veri tabanı sitemlerinde SRIDxxx şeklinde tanımlı. WGS-84 için kullanılan numara ise SRID 4326.

SRID ile veri tabanına satır girme örneği burada.

.shp dosyası - Shapefile Nedir
Bu dosyanın formatı açık kaynaktır. .shp dosyaları feature geometry bilgisini saklar.  Bir .shp dosyasında sadece bir tür geometry type olabilir. Geometry type listesi şöyledir. Dosyanın boyutu en  fazla 2GB civarında olabilir.
Value                                 Shape Type
0                                     Null Shape
1                                     Point
3                                     PolyLine
5                                     Polygon
8                                     MultiPoint
11                                    PointZ
13                                    PolyLineZ
15                                    PolygonZ
18                                    MultiPointZ
21                                    PointM
23                                    PolyLineM
25                                    PolygonM
28                                    MultiPointM
31                                    MultiPatch
2. ArcGIS Nedir?
ArcGIS, ESRI tarafından geliştirilen  bir yazılım

ArcGIS bir çok dosyadan oluşmakta. Dosyaların açıklaması şöyle.
Mandatory files
  • .shp — shape format; the feature geometry itself
  • .shx — shape index format; a positional index of the feature geometry to allow seeking forwards and backwards quickly
  • .dbf — attribute format; columnar attributes for each shape, in dBase IV format
Other files
  • .prj — projection format; the coordinate system and projection information, a plain text file describing the projection using well-known text format
  • .sbn and .sbx — a spatial index of the features
  • .fbn and .fbx — a spatial index of the features that are read-only
  • .ain and .aih — an attribute index of the active fields in a table
  • .ixs — a geocoding index for read-write datasets
  • .mxs — a geocoding index for read-write datasets (ODB format)
  • .atx — an attribute index for the .dbf file in the form of shapefile.columnname.atx (ArcGIS 8 and later)
  • .shp.xml — geospatial metadata in XML format, such as ISO 19115 or other XML schema
  • .cpg — used to specify the code page (only for .dbf) for identifying the character encoding to be used
  • .qix — an alternative quadtree spatial index used by MapServer and GDAL/OGR software
.sbn Dosyası
Açıklaması şöyle
If ArcGIS is used to create a spatial index it adds sbn and sbx files to the shapefile collection. QGIS can read these but not write or update them. QGIS can create qix spatial indexes that ArcGIS can't see,...
3. QGIS
Açıklaması şöyle
The only thing not compatible between ArcGIS and QGIS are the style files which come with some shapefiles : *.lyr, *.style for ArcGIS and *.qml, *.sld for QGIS.
Geometry generators
Açıklaması şöyle
One layer can only contain one type of geometry: either points or polygons (or lines), but not both.

However, using Geometry generators, you can create symbolization (not actual geometries) of another geometry type.

















10 Aralık 2018 Pazartesi

Expression (Ifade) Parse Etme

Giriş
Bu yazı tamamen konu hakkında anladıklarımın özeti. Her anladığım, doğru olmayabilir.

Yazıda syntax (söz dizim), semantics (anlam/yorum) gibi konulara girmiyorum. Çok basit bir yazı olsun istedim.

Konuyla ilgili olarak Gramer başlıklı yazıya da göz atabilirsiniz.

Statement (Deyim) Nedir?
Wikipedia şöyle tanımlıyor.
In computer programming, a statement is the smallest standalone element of an imperative programming language that expresses some action to be carried out.
Basit bir örnek vermek gerekirse statement konuşma dilindeki tam bir cümle gibi düşünülebilir. Konuşma dilinde cümle nasıl nokta ile bitiyorsa statement ta çoğu dilde ; karakteri ile biter. C dilindeki statement grameri şöyledir.
stat        : labeled_stat
            | exp_stat
            | compound_stat
            | selection_stat
            | iteration_stat
            | jump_stat
            ;
Gramerde statement'ın exp_stat yani expression statement'lardan oluşabileceği görülüyor. Expression statement ise şöyledir.
exp_stat    : exp ';'
            |   ';'
            ;
Expression (İfade) Nedir?
Expression (İfade) tek değerden ibaret kod parçasıdır.Expression (İfade), Statement'tan (deyim)  farklıdır. Örneğin
for(i = 0; i < (1 << 7); i++)
satırında 1 << 7 constant bir expression'dır. Çünkü 128 değerini döner.
Örnek
Java'da lambda body expressin'dan oluşursa blok içine alınmaz. Ancak throw bir statement(deyim) oldupu için blok içinde kullanılması gerekir. Dolayısıyla şu kod derlenmez.
Supplier<Long> asd = () -> throw new RuntimeException(); // This won't compile :(
Şöyle yaparız.
Supplier<Long> asd = () -> {
    throw new RuntimeException();
};
Örnek
Bir statement tek bir expression'dan oluşamaz. Elimizde şöyle bir kod olsun.
public static void main(String[] args)
{
  1+2;
}
Şu çıktıyı alırız.
Main.java:5: error: not a statement
        1+2;
         ^
1 error
Expression Java Language Specification'da (JLS) şöyledir.
ExpressionStatement:
  StatementExpression ;

StatementExpression:
  Assignment 
  PreIncrementExpression 
  PreDecrementExpression 
  PostIncrementExpression 
  PostDecrementExpression 
  MethodInvocation 
  ClassInstanceCreationExpression
Expression Nasıl Parse Edilir?
Lexer veya Scanner
İfade daha küçük parçalara ayırılmalıdır. Bu işlemi yapan programa Lexer denilir. Lexer'in çıktısı Token'lardır. Tokenlar Operator (İşlem) ve Operand (İşlenen) olarak ayrılırlar. Bir çok lexer düzenli ifadeler (regular expression) ile ayırma işlemi yapar.

Aşağıda lexer ile kullanılan bazı düzenli ifade örnekleri var:
number := [digit][digit|underscore]+
reserved_word := 'if' | 'then' | 'else' | 'for' | 'while' | ...
identifier := [letter][letter|digit|underscore]*
assignment_operator := '=' | '+=' | '-=' | '*=' | '/=' 
addition_operator := '+' | '-' 
multiplication_operator := '*' | '/' | '%'
Lex
En çok kullanılan lexer'lardan biris lex uygulaması. lex aslında lexer üreten bir uygulama. Üretilen kod çoğu lexer gibi 2 boyutlu state transition tabloları kullanıyor.

Token Tree
Burada matematiksel bir ifadeyi çalıştıran örnek bir uygulama var. Ayırım neticesinde işlemlerin öncelik sırasına göre bir ağaç yapısı oluşturulur.

Her zaman ağaç yapısı oluşturulmak zorunda değildir. Başka yapılar da kullanılabilir. örneğin, stack (yığıt) yapısı da kullanıma çok uygundur.

Java
Örnek
Token şöyle. Satır ile çalıştığımız için başlangıç ve bitiş konumunu bilmek yeterli. Eğer satırla çalışmasaydım muhtemelen token değerini de bir bellek alanında saklama gerekirdi.
public class Token<T> { T type; int start int stop; }
Lexer temeli şöyle
public abstract class AbstractLineLexer<T> {
String line; //Position is incremented by inheriting Lexer int pos; private final Token[] lookAheadTokens; private int lookAheadPosition; private int lookAheadLength; AbstractLineLexer(int k) { lookAheadTokens = new Token[k + 1]; for (int i = 0; i < lookAheadTokens.length; i++) { lookAheadTokens[i] = new Token(); } } public void setLine(String line) { this.line = line; this.pos = 0; this.lookAheadPosition = 0; this.lookAheadLength = 0; } public Token<T> consume() throws Exception {...} public Token<T> lookAhead(int k) throws Exception {....} //Read next token from input into token object. protected abstract void readToken(Token<TYPE> token) throws MalformedBatchException; }
Esas kod şöyle. Burada circular buffer şeklinde bir yapı var. lookAhead() ile istenilen sayıda token circular buffer'a dolduruluyor ve en son token döndürülüyor. Eğer istenirse consume() ile token'lar birer birer de tüketilebilir.
Token<T> consume() throws Exception {
  if (lookAheadLength == 0) {
    lookAhead(1);
  }
  lookAheadLength--;
  lookAheadPosition = (lookAheadPosition + 1) % lookAheadTokens.length;
  return lookAheadTokens[lookAheadPosition];
}

Token<T> lookAhead(int k) throws Exception {
  if (k >= lookAheadTokens.length || k < 0) {
    throw new IllegalStateException("Invalid look ahead value: " + k);
  }
  while (lookAheadLength <= k) {
    Token token = lookAheadTokens[(lookAheadPosition + lookAheadLength++) 
      % lookAheadTokens.length]
    readToken(token);
  }
  return lookAheadTokens[(lookAheadPosition + k) % lookAheadTokens.length];
}
Kalıtan Lexer'ın token tipleri şöyle
enum TokenType {
  ENTRY_BEGIN("{"),
  ENTRY_END("}"),
  ARRAY_BEGIN("["),
  ARRAY_END("]"),
  ARRAY_SEPARATOR(","),
  SEPARATOR("|"),
  STRING("String"),
  IDENTIFIER("Identifier"),
  EOL("End of line");

  final String name;

  TokenType(String name) {
    this.name = name;
  }
}
Lexer ise şöyle
public class Lexer extends AbstractLineLexer<TokenType> {

  Lexer(int k) {
    super(k);
  }

  @Override
  public void readToken(Token<TokenType> token) throws MalformedBatchException {
    token.start = pos; //Save start position of token
    if (token.start == line.length()) {
      token.type = TokenType.EOL;
    } else {
      token.type = readToken();
    }
    token.stop = pos; //Save stop position of token
  }

  protected TokenType readToken() throws MalformedBatchException {
    char c = line.charAt(pos++);
    switch (c) {
      case '{':
        return TokenType.ENTRY_BEGIN;
      case '}':
        return TokenType.ENTRY_END;
      case '[':
        return TokenType.ARRAY_BEGIN;
      case ']':
        return TokenType.ARRAY_END;
      case ',':
        return TokenType.ARRAY_SEPARATOR;
      case '|':
        return TokenType.SEPARATOR;
      case '"':
        while (pos < line.length()) {
          if (line.charAt(pos++) == '"') {
            return TokenType.STRING;
          }
        }
        throw new Exception("Expected character '\"'", line.length());
      default:
        if (isIdChar(c)) {
          while (pos < line.length() && isIdChar(line.charAt(pos))) {
            pos++;
          }
          return TokenType.IDENTIFIER;
        } else {
          throw new Exception("Unexpected character '" + c + "'", pos - 1);
        }
      }
    }

  private boolean isIdChar(char c) {
    return c != '"' && c != '|' && c != '{' && c != '}' && c != '[' && c != ']' 
      && c != ',';
  }
}