Решение на Фабрика за регулярни изрази от Александър Деспотов

Обратно към всички решения

Към профила на Александър Деспотов

Резултати

  • 8 точки от тестове
  • 0 бонус точки
  • 8 точки общо
  • 7 успешни тест(а)
  • 2 неуспешни тест(а)

Код

package main
import (
"errors"
"regexp"
"strconv"
"sync"
)
var idCnt int
const (
DOES_NOT_EXIST = iota
ENQUEUED
IN_PROGRESS
UNABLE_TO_PRODUCE
DONE
)
type Order struct {
Id string
Status int
Words []string
Result string
Channel chan *Order
}
func NewOrder(words []string, channel chan *Order) *Order {
var tmp Order
tmp.Id = strconv.Itoa(idCnt)
idCnt++
tmp.Status = ENQUEUED
tmp.Words = words
tmp.Result = ""
tmp.Channel = make(chan *Order)
return &tmp
}
type Client struct {
Name string
Orders map[string]*Order
Channel chan *Order
}
func NewClient(name string) *Client {
var tmp Client
tmp.Name = name
tmp.Orders = make(map[string]*Order)
tmp.Channel = make(chan *Order)
return &tmp
}
func (c *Client) Order(factory *Factory, words []string) string {
order := NewOrder(words, c.Channel)
c.Orders[order.Id] = order
factory.Enqueue(order)
return order.Id
}
func (c *Client) CheckStatus(id string) int {
val, ok := c.Orders[id]
if !ok {
return DOES_NOT_EXIST
}
return val.Status
}
type Factory struct {
WorkersCnt uint8
Materials map[string]uint16
working bool
Queue chan *Order
mutex sync.Mutex
}
func NewFactory(workers uint8) *Factory {
var tmp Factory
tmp.WorkersCnt = workers
tmp.Materials = make(map[string]uint16, 0)
tmp.Queue = make(chan *Order, 1024)
tmp.working = false
return &tmp
}
func (f *Factory) Enqueue(order *Order) {
f.Queue <- order
}
func (f *Factory) work() {
for f.working {
if f.WorkersCnt != 0 {
go f.processOrder()
f.mutex.Lock()
f.WorkersCnt--
f.mutex.Unlock()
}
}
}
func (f *Factory) StartProducing() {
f.working = true
go f.work()
}
func (f *Factory) StopProducing() {
f.working = false
}
func (f *Factory) StorageAdd(materials map[string]uint16) {
for key, val := range materials {
if _, ok := f.Materials[key]; ok {
f.Materials[key] += val
} else {
f.Materials[key] = val
}
}
}
func (f *Factory) processOrder() {
order := <-f.Queue
order.Status = IN_PROGRESS
res, err := f.generateRegexp(order.Words)
if err != nil {
order.Result = ""
order.Status = UNABLE_TO_PRODUCE
} else {
order.Result = res
order.Status = DONE
}
f.mutex.Lock()
f.WorkersCnt++
f.mutex.Unlock()
}
func (f *Factory) genRegexp(needed []string, tmpMat map[string]uint16) []string {
res := make([]string, 0)
for idx, _ := range tmpMat {
regex, err := regexp.Compile("^" + idx)
if err != nil {
continue
}
nextNeeded := make([]string, 0)
for _, word := range needed {
if regex.MatchString(word) {
nextNeeded = append(nextNeeded, regex.ReplaceAllString(word, ""))
}
}
if len(nextNeeded) == len(needed) {
res = append(res, idx)
for _, newWord := range nextNeeded {
if newWord != "" {
newTmpMat := make(map[string]uint16)
newTmpMat = tmpMat
newTmpMat[idx] -= 1
newParts := f.genRegexp(nextNeeded, newTmpMat)
res = append(res, newParts...)
break
}
}
return res
}
}
return res
}
func (f *Factory) generateRegexp(words []string) (string, error) {
tmpMat := make(map[string]uint16)
tmpMat = f.Materials
regArr := f.genRegexp(words, tmpMat)
res := ""
if ok := f.GetMaterials(regArr); ok {
for _, val := range regArr {
res += val
}
} else {
return res, errors.New("Unable to produce!")
}
return "^" + res + "$", nil
}
func (f *Factory) GetMaterials(needed []string) bool {
f.mutex.Lock()
defer f.mutex.Unlock()
for idx, val := range needed {
if _, ok := f.Materials[val]; ok {
if f.Materials[val] == 0 {
delete(f.Materials, val)
} else {
f.Materials[val]--
}
} else {
for i := 0; i < idx; i++ {
add := map[string]uint16{needed[i]: 1}
f.StorageAdd(add)
}
return false
}
}
return true
}

Лог от изпълнението

PASS
ok  	_/tmp/d20150111-18989-14oislg	0.020s
PASS
ok  	_/tmp/d20150111-18989-14oislg	0.003s
--- FAIL: TestUnableToProcessOnEmptyStorage (0.00 seconds)
	solution_test.go:33: Not unable to process with empty storage
FAIL
exit status 1
FAIL	_/tmp/d20150111-18989-14oislg	0.003s
--- FAIL: TestUnableToProcessOnEmptyStorage (0.00 seconds)
	solution_test.go:33: Not unable to process with empty storage
--- FAIL: TestUnableToProcess (0.00 seconds)
	solution_test.go:47: Not unable to process with lack of materials
FAIL
exit status 1
FAIL	_/tmp/d20150111-18989-14oislg	0.003s
PASS
ok  	_/tmp/d20150111-18989-14oislg	0.003s
PASS
ok  	_/tmp/d20150111-18989-14oislg	0.003s
PASS
ok  	_/tmp/d20150111-18989-14oislg	0.003s
PASS
ok  	_/tmp/d20150111-18989-14oislg	0.003s
PASS
ok  	_/tmp/d20150111-18989-14oislg	0.003s

История (1 версия и 0 коментара)

Александър обнови решението на 31.12.2014 19:18 (преди над 3 години)

+package main
+
+import (
+ "errors"
+ "regexp"
+ "strconv"
+ "sync"
+)
+
+var idCnt int
+
+const (
+ DOES_NOT_EXIST = iota
+ ENQUEUED
+ IN_PROGRESS
+ UNABLE_TO_PRODUCE
+ DONE
+)
+
+type Order struct {
+ Id string
+ Status int
+ Words []string
+ Result string
+ Channel chan *Order
+}
+
+func NewOrder(words []string, channel chan *Order) *Order {
+ var tmp Order
+ tmp.Id = strconv.Itoa(idCnt)
+ idCnt++
+ tmp.Status = ENQUEUED
+ tmp.Words = words
+ tmp.Result = ""
+ tmp.Channel = make(chan *Order)
+ return &tmp
+}
+
+type Client struct {
+ Name string
+ Orders map[string]*Order
+ Channel chan *Order
+}
+
+func NewClient(name string) *Client {
+ var tmp Client
+ tmp.Name = name
+ tmp.Orders = make(map[string]*Order)
+ tmp.Channel = make(chan *Order)
+ return &tmp
+}
+
+func (c *Client) Order(factory *Factory, words []string) string {
+ order := NewOrder(words, c.Channel)
+ c.Orders[order.Id] = order
+ factory.Enqueue(order)
+ return order.Id
+}
+
+func (c *Client) CheckStatus(id string) int {
+ val, ok := c.Orders[id]
+ if !ok {
+ return DOES_NOT_EXIST
+ }
+ return val.Status
+}
+
+type Factory struct {
+ WorkersCnt uint8
+ Materials map[string]uint16
+ working bool
+ Queue chan *Order
+ mutex sync.Mutex
+}
+
+func NewFactory(workers uint8) *Factory {
+ var tmp Factory
+ tmp.WorkersCnt = workers
+ tmp.Materials = make(map[string]uint16, 0)
+ tmp.Queue = make(chan *Order, 1024)
+ tmp.working = false
+ return &tmp
+}
+
+func (f *Factory) Enqueue(order *Order) {
+ f.Queue <- order
+}
+
+func (f *Factory) work() {
+ for f.working {
+ if f.WorkersCnt != 0 {
+ go f.processOrder()
+ f.mutex.Lock()
+ f.WorkersCnt--
+ f.mutex.Unlock()
+ }
+ }
+}
+
+func (f *Factory) StartProducing() {
+ f.working = true
+ go f.work()
+}
+
+func (f *Factory) StopProducing() {
+ f.working = false
+}
+
+func (f *Factory) StorageAdd(materials map[string]uint16) {
+ for key, val := range materials {
+ if _, ok := f.Materials[key]; ok {
+ f.Materials[key] += val
+ } else {
+ f.Materials[key] = val
+ }
+ }
+}
+
+func (f *Factory) processOrder() {
+ order := <-f.Queue
+ order.Status = IN_PROGRESS
+ res, err := f.generateRegexp(order.Words)
+ if err != nil {
+ order.Result = ""
+ order.Status = UNABLE_TO_PRODUCE
+ } else {
+ order.Result = res
+ order.Status = DONE
+ }
+ f.mutex.Lock()
+ f.WorkersCnt++
+ f.mutex.Unlock()
+
+}
+
+func (f *Factory) genRegexp(needed []string, tmpMat map[string]uint16) []string {
+ res := make([]string, 0)
+ for idx, _ := range tmpMat {
+ regex, err := regexp.Compile("^" + idx)
+ if err != nil {
+ continue
+ }
+
+ nextNeeded := make([]string, 0)
+ for _, word := range needed {
+ if regex.MatchString(word) {
+ nextNeeded = append(nextNeeded, regex.ReplaceAllString(word, ""))
+ }
+ }
+
+ if len(nextNeeded) == len(needed) {
+ res = append(res, idx)
+ for _, newWord := range nextNeeded {
+ if newWord != "" {
+ newTmpMat := make(map[string]uint16)
+ newTmpMat = tmpMat
+ newTmpMat[idx] -= 1
+ newParts := f.genRegexp(nextNeeded, newTmpMat)
+ res = append(res, newParts...)
+ break
+ }
+ }
+ return res
+ }
+ }
+ return res
+}
+
+func (f *Factory) generateRegexp(words []string) (string, error) {
+
+ tmpMat := make(map[string]uint16)
+ tmpMat = f.Materials
+ regArr := f.genRegexp(words, tmpMat)
+ res := ""
+ if ok := f.GetMaterials(regArr); ok {
+ for _, val := range regArr {
+ res += val
+ }
+ } else {
+ return res, errors.New("Unable to produce!")
+ }
+ return "^" + res + "$", nil
+}
+
+func (f *Factory) GetMaterials(needed []string) bool {
+ f.mutex.Lock()
+ defer f.mutex.Unlock()
+ for idx, val := range needed {
+ if _, ok := f.Materials[val]; ok {
+ if f.Materials[val] == 0 {
+ delete(f.Materials, val)
+ } else {
+ f.Materials[val]--
+ }
+ } else {
+ for i := 0; i < idx; i++ {
+ add := map[string]uint16{needed[i]: 1}
+ f.StorageAdd(add)
+ }
+ return false
+ }
+ }
+ return true
+}