/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.

    * Neither the name of "The Computer Language Benchmarks Game" nor the
    name of "The Computer Language Shootout Benchmarks" nor the names of
    its contributors may be used to endorse or promote products derived
    from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/

/* The Computer Language Benchmarks Game
 * http://shootout.alioth.debian.org/
 *
 * contributed by The Go Authors.
 * Based on C program by by Petr Prokhorenkov.
 */

package main

import (
	"bytes"
	"flag"
	"os"
)

var out = make(buffer, 0, 32768)

var n = flag.Int("n", 1000, "length of result")

const Line = 60

func Repeat(alu []byte, n int) {
	buf := bytes.Add(alu, alu)
	off := 0
	for n > 0 {
		m := n
		if m > Line {
			m = Line
		}
		buf1 := out.NextWrite(m + 1)
		copy(buf1, buf[off:])
		buf1[m] = '\n'
		if off += m; off >= len(alu) {
			off -= len(alu)
		}
		n -= m
	}
}

const (
	IM = 139968
	IA = 3877
	IC = 29573

	LookupSize  = 4096
	LookupScale float64 = LookupSize - 1
)

var rand uint32 = 42

type Acid struct {
	sym   byte
	prob  float64
	cprob float64
	next  *Acid
}

func computeLookup(acid []Acid) *[LookupSize]*Acid {
	var lookup [LookupSize]*Acid
	var p float64
	for i := range acid {
		p += acid[i].prob
		acid[i].cprob = p * LookupScale
		if i > 0 {
			acid[i-1].next = &acid[i]
		}
	}
	acid[len(acid)-1].cprob = 1.0 * LookupScale

	j := 0
	for i := range lookup {
		for acid[j].cprob < float64(i) {
			j++
		}
		lookup[i] = &acid[j]
	}

	return &lookup
}

func Random(acid []Acid, n int) {
	lookup := computeLookup(acid)
	for n > 0 {
		m := n
		if m > Line {
			m = Line
		}
		buf := out.NextWrite(m + 1)
		f := LookupScale / IM
		myrand := rand
		for i := 0; i < m; i++ {
			myrand = (myrand*IA + IC) % IM
			r := float64(int(myrand)) * f
			a := lookup[int(r)]
			for a.cprob < r {
				a = a.next
			}
			buf[i] = a.sym
		}
		rand = myrand
		buf[m] = '\n'
		n -= m
	}
}

func main() {
	defer out.Flush()

	flag.Parse()

	iub := []Acid{
		Acid{prob: 0.27, sym: 'a'},
		Acid{prob: 0.12, sym: 'c'},
		Acid{prob: 0.12, sym: 'g'},
		Acid{prob: 0.27, sym: 't'},
		Acid{prob: 0.02, sym: 'B'},
		Acid{prob: 0.02, sym: 'D'},
		Acid{prob: 0.02, sym: 'H'},
		Acid{prob: 0.02, sym: 'K'},
		Acid{prob: 0.02, sym: 'M'},
		Acid{prob: 0.02, sym: 'N'},
		Acid{prob: 0.02, sym: 'R'},
		Acid{prob: 0.02, sym: 'S'},
		Acid{prob: 0.02, sym: 'V'},
		Acid{prob: 0.02, sym: 'W'},
		Acid{prob: 0.02, sym: 'Y'},
	}

	homosapiens := []Acid{
		Acid{prob: 0.3029549426680, sym: 'a'},
		Acid{prob: 0.1979883004921, sym: 'c'},
		Acid{prob: 0.1975473066391, sym: 'g'},
		Acid{prob: 0.3015094502008, sym: 't'},
	}

	alu := []byte(
		"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
			"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
			"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
			"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
			"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
			"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
			"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA")

	out.WriteString(">ONE Homo sapiens alu\n")
	Repeat(alu, 2**n)
	out.WriteString(">TWO IUB ambiguity codes\n")
	Random(iub, 3**n)
	out.WriteString(">THREE Homo sapiens frequency\n")
	Random(homosapiens, 5**n)
}


type buffer []byte

func (b *buffer) Flush() {
	p := *b
	if len(p) > 0 {
		os.Stdout.Write(p)
	}
	*b = p[0:0]
}

func (b *buffer) WriteString(s string) {
	p := b.NextWrite(len(s))
	for i := 0; i < len(s); i++ {
		p[i] = s[i]
	}
}

func (b *buffer) NextWrite(n int) []byte {
	p := *b
	if len(p)+n > cap(p) {
		b.Flush()
		p = *b
	}
	out := p[len(p) : len(p)+n]
	*b = p[0 : len(p)+n]
	return out
}
