// Autogenerated with DRAKON Editor 1.29

package main

import (
	"fmt"
)

type Var int

type Objects []interface{}
type Comparator func(interface{}, interface{}) int



func  Fibonacci(n int) []int {
    // item 300
    result := []int{0}
    // item 2860001
    if n == 0 {
        
    } else {
        // item 2860002
        if n == 1 {
            // item 301
            result = append(result, 1)
        } else {
            // item 304
            result = append(result, 1)
            // item 303
            f0 := 0
            f1 := 1
            // item 2930001
            i := 2;
            for {
                // item 2930002
                if i <= n {
                    
                } else {
                    break
                }
                // item 294
                fib := f0 + f1
                f0, f1 = f1, fib
                // item 305
                result = append(result, fib)
                // item 2930003
                i++;
            }
        }
    }
    // item 298
    return result
}

func  Quicksort(comparer Comparator, collection Objects, begin int, end int)  {
    // item 405
    length := end - begin
    last := end - 1
    // item 4060001
    if (length == 0) || (length == 1) {
        
    } else {
        // item 4060003
        if length == 2 {
            // item 421
            if compare(comparer, collection, begin, last) <= 0 {
                
            } else {
                // item 422
                swap(collection, begin, last)
            }
        } else {
            // item 425
            pivotIndex := begin + length / 2
            // item 433
            swap(collection, pivotIndex, last)
            storeIndex := begin
            // item 4260001
            i := begin;
            for {
                // item 4260002
                if i < last {
                    
                } else {
                    break
                }
                // item 434
                if compare(comparer, collection, i, last) < 0 {
                    // item 435
                    swap(collection, i, storeIndex)
                    storeIndex++
                } else {
                    
                }
                // item 4260003
                i++;
            }
            // item 438
            swap(collection, storeIndex, last)
            // item 439
            Quicksort(comparer, collection, begin, storeIndex)
            // item 440
            Quicksort(comparer, collection, storeIndex + 1, end)
        }
    }
}

func  Sort(list Objects, comparer Comparator)  {
    // item 373
    Quicksort(comparer, list, 0, len(list))
}

func  assertEqual(a int, b int)  {
    // item 175
    if a == b {
        
    } else {
        // item 178
        panic("assert failed")
    }
}

func  columnNN(nna bool, nnb bool) int {
    // item 181
    var nnm int
    // item 125
    if (nna) || (nnb) {
        // item 130
        nnm = 2
    } else {
        // item 129
        nnm = 1
    }
    // item 133
    return nnm
}

func  columnNY(nya bool, nyb bool) int {
    // item 182
    var nym int
    // item 113
    if (nya) || (!(nyb)) {
        // item 118
        nym = 2
    } else {
        // item 117
        nym = 1
    }
    // item 121
    return nym
}

func  columnYN(yna bool, ynb bool) int {
    // item 183
    var ynm int
    // item 101
    if (yna) && (!(ynb)) {
        // item 105
        ynm = 1
    } else {
        // item 106
        ynm = 2
    }
    // item 109
    return ynm
}

func  columnYY(yya bool, yyb bool) int {
    // item 184
    var yym int
    // item 47
    if (yya) && (yyb) {
        // item 51
        yym = 1
    } else {
        // item 52
        yym = 2
    }
    // item 55
    return yym
}

func  compare(comparer Comparator, array Objects, a int, b int) int {
    // item 457
    left := array[a]
    right := array[b]
    // item 458
    return comparer(left, right)
}

func  complex1(x1 bool, x2 bool, x3 bool, x4 bool) int {
    // item 137
    if ((x1) && (!(x2))) || (!((x3) || (!(x4)))) {
        // item 143
        return 1
    } else {
        // item 148
        return 2
    }
}

func  complex2(x1 bool, x2 bool, x3 bool, x4 bool) int {
    // item 152
    if ((x1) || (!(x2))) && (!((x3) && (!(x4)))) {
        // item 158
        return 1
    } else {
        // item 163
        return 2
    }
}

func  foreachDemo()  {
    // item 235
    fmt.Println("Iteration demo")
    // item 233
    var sequence []int = Fibonacci(15)
    // item 234
    printListArrow(sequence)
    printListFor(sequence)
    printListForeach(sequence)
    // item 236
    fmt.Println("")
    // item 239
    testEarly(20, 60)
    // item 240
    testEarly(35, 70)
    // item 241
    testEarly(4, 0)
}

func  foreachEarlyExit(value int) int {
    // item 270
    found := -1
    var normal_254 int
    normal_254 = 1
    for _, x := range []int{10, 20, 30} {
        // item 258
        if x == value {
            // item 262
            found = x
            normal_254 = 0
            break
        } else {
            
        }
    }
    if normal_254 == 1 {
        // item 261
        found = 0
    }
    for _, x := range []int{40, 20, 70} {
        // item 269
        m := x / 2
        // item 264
        if m == value {
            // item 268
            return x + found
        } else {
            
        }
    }
    // item 267
    return 0
}

func  main()  {
    // item 180
    testShortCircuit()
    // item 307
    foreachDemo()
    // item 318
    fmt.Println("Method demo")
    // item 27
    x := Var(20)
    y := x.printAdd(5)
    
    fmt.Println(y)
    // item 320
    fmt.Println("")
    // item 459
    quicksortDemo()
}

func  print(collection Objects)  {
    for _, item := range collection {
        // item 366
        fmt.Printf("%s ", item)
    }
    // item 374
    fmt.Println("")
}

func (self Var) printAdd(value int) Var {
    // item 314
    newValue := int(self) + value
    // item 316
    fmt.Printf("%d -> %d\n", int(self), newValue)
    // item 315
    return Var(newValue)
}

func  printListArrow(collection []int)  {
    // item 211
    fmt.Println("using if and arrow:")
    // item 206
    length := len(collection)
    i := 0
    for {
        // item 207
        if i < length {
            
        } else {
            break
        }
        // item 205
        item := collection[i]
        write(item)
        // item 209
        i++
    }
    // item 212
    fmt.Println("")
}

func  printListFor(collection []int)  {
    // item 219
    fmt.Println("using for:")
    // item 223
    length := len(collection)
    // item 2170001
    i := 0;
    for {
        // item 2170002
        if i < length {
            
        } else {
            break
        }
        // item 222
        write(collection[i])
        // item 2170003
        i++;
    }
    // item 220
    fmt.Println("")
}

func  printListForeach(collection []int)  {
    // item 198
    fmt.Println("using foreach:")
    for key, value := range collection {
        // item 195
        fmt.Printf("%d->%d ", key, value)
    }
    // item 197
    fmt.Println("")
}

func  quicksortDemo()  {
    // item 328
    fmt.Println("quick sort demo")
    // item 324
     unsorted := Objects { "the", "sooner", "we", "start", "this", "the", "better" }
     sorted   := Objects { "aa", "bb", "cc", "dd", "ee", "ff" }
     reverse  := Objects { "ff", "ee", "dd", "cc", "bb", "aa" }
     empty    := Objects {}
     flat     := Objects { "flat", "flat", "flat", "flat", "flat" }
    // item 325
    comparer := reverseStringComparer
    // item 332
    Sort(unsorted, comparer)
    Sort(sorted, comparer)
    Sort(reverse, comparer)
    Sort(empty, comparer)
    Sort(flat, comparer)
    // item 326
    print(unsorted)
    print(sorted)
    print(reverse)
    print(empty)
    print(flat)
    // item 327
    stringsAreSorted(unsorted)
    stringsAreSorted(sorted)
    stringsAreSorted(reverse)
    stringsAreSorted(empty)
    stringsAreSorted(flat)
    // item 331
    fmt.Println()
}

func  reverseStringComparer(left interface{}, right interface{}) int {
    // item 380
    ls := left.(string)
    rs := right.(string)
    // item 3810001
    if ls < rs {
        // item 391
        return 1
    } else {
        // item 3810002
        if ls == rs {
            // item 390
            return 0
        } else {
            // item 388
            return -1
        }
    }
}

func  stairsNN(nnas bool, nnbs bool) int {
    // item 185
    var nnms int
    // item 87
    if (nnas) && (nnbs) {
        // item 94
        nnms = 2
    } else {
        // item 93
        nnms = 1
    }
    // item 97
    return nnms
}

func  stairsNY(nyas bool, nybs bool) int {
    // item 186
    var nyms int
    // item 73
    if (nyas) && (!(nybs)) {
        // item 80
        nyms = 2
    } else {
        // item 79
        nyms = 1
    }
    // item 83
    return nyms
}

func  stairsYN(ynas bool, ynbs bool) int {
    // item 187
    var ynms int
    // item 59
    if (ynas) || (!(ynbs)) {
        // item 65
        ynms = 1
    } else {
        // item 66
        ynms = 2
    }
    // item 69
    return ynms
}

func  stairsYY(yyas bool, yybs bool) int {
    // item 188
    var yyms int
    // item 33
    if (yyas) || (yybs) {
        // item 39
        yyms = 1
    } else {
        // item 40
        yyms = 2
    }
    // item 43
    return yyms
}

func  stringsAreSorted(array Objects)  {
    // item 3380001
    i := 1;
    for {
        // item 3380002
        if i < len(array) {
            
        } else {
            break
        }
        // item 358
        before := array[i - 1].(string)
        current := array[i].(string)
        // item 448
        if before < current {
            // item 451
            panic("strings are not sorted")
            break
        } else {
            
        }
        // item 3380003
        i++;
    }
}

func  swap(array Objects, leftIndex int, rightIndex int)  {
    // item 447
    left := array[leftIndex];
    right := array[rightIndex];
    // item 446
    array[leftIndex] = right
    array[rightIndex ] = left
}

func  testEarly(value int, expected int)  {
    // item 277
    var actual int = foreachEarlyExit(value)
    // item 278
    if actual == expected {
        
    } else {
        // item 281
        panic("foreach_early_exit failed")
    }
}

func  testShortCircuit()  {
    // item 308
    fmt.Println("Short-circuit test")
    // item 179
    assertEqual(columnNN(false, false), 1)
    assertEqual(columnNN(false, true ), 2)
    assertEqual(columnNN(true,  false), 2)
    assertEqual(columnNN(true,  true ), 2)
    assertEqual(columnNY(false, false), 2)
    assertEqual(columnNY(false, true ), 1)
    assertEqual(columnNY(true,  false), 2)
    assertEqual(columnNY(true,  true ), 2)
    assertEqual(columnYN(false, false), 2)
    assertEqual(columnYN(false, true ), 2)
    assertEqual(columnYN(true,  false), 1)
    assertEqual(columnYN(true,  true ), 2)
    assertEqual(columnYY(false, false), 2)
    assertEqual(columnYY(false, true ), 2)
    assertEqual(columnYY(true,  false), 2)
    assertEqual(columnYY(true,  true ), 1)
    assertEqual(stairsNN(false, false), 1)
    assertEqual(stairsNN(false, true ), 1)
    assertEqual(stairsNN(true,  false), 1)
    assertEqual(stairsNN(true,  true ), 2)
    assertEqual(stairsNY(false, false), 1)
    assertEqual(stairsNY(false, true ), 1)
    assertEqual(stairsNY(true,  false), 2)
    assertEqual(stairsNY(true,  true ), 1)
    assertEqual(stairsYN(false, false), 1)
    assertEqual(stairsYN(false, true ), 2)
    assertEqual(stairsYN(true,  false), 1)
    assertEqual(stairsYN(true,  true ), 1)
    assertEqual(stairsYY(false, false), 2)
    assertEqual(stairsYY(false, true ), 1)
    assertEqual(stairsYY(true,  false), 1)
    assertEqual(stairsYY(true,  true ), 1)
    // item 319
    fmt.Println("")
}

func  write(item int)  {
    // item 229
    fmt.Printf("%d ", item)
}

// I am the footer.
// Символы Юникод
