项目作者: pen

项目描述 :
split a slice into sub-slices which their sum of elements are close to same. [配列][分割][アルゴリズム]
高级语言: Go
项目地址: git://github.com/pen/split-slice-go.git
创建时间: 2021-06-11T00:00:32Z
项目社区:https://github.com/pen/split-slice-go

开源协议:MIT License

下载


split-slice-go

概要

スライスを複数のスライスに分割する。
このとき分割後の各スライスの要素の“大きさ”の合計をできるだけ均等にする。

用例

  1. The sun shines bright in the old Kentucky home

を空白の位置で折り返し、3行でボックスに表示したい(等幅フォントを仮定)。
このときボックスの幅を可能な限り狭くしたい。

だめな解:

  1. The sun shines bright in the
  2. old
  3. Kentucky home

ベストの解(この文字列の場合は2個ある):

  1. The sun shines
  2. bright in the
  3. old Kentucky home
  1. The sun shines
  2. bright in the old
  3. Kentucky home

使い方

  1. import split "github.com/pen/split-slice-go"
  2. // :
  3. result := split.Sentence(
  4. "I have a pen. I have an apple.", // 分割したい文字列
  5. 2, // 分割数
  6. false, // 長い行を早めに出すか?
  7. )

3番目の引数は、前節の例において2つの解のどちらを返すかを指定することにあたる。

これにより結果が大きく異る場合もある。

  1. package main
  2. import (
  3. "fmt"
  4. split "github.com/pen/split-slice-go"
  5. )
  6. func main() {
  7. sentence := `Are hackers a threat?` +
  8. ` The degree of threat presented by any conduct,` +
  9. ` whether legal or illegal,` +
  10. ` depends on the actions and` +
  11. ` intent of the individual and the harm they cause.`
  12. fmt.Printf("%s\n", split.Sentence(sentence, 7, false))
  13. fmt.Println("--------------------------")
  14. fmt.Printf("%s\n", split.Sentence(sentence, 7, true))
  15. }
  1. $ go run sample.go
  2. Are hackers a threat?
  3. The degree of threat
  4. presented by any conduct,
  5. whether legal or illegal,
  6. depends on the actions and
  7. intent of the individual
  8. and the harm they cause.
  9. --------------------------
  10. Are hackers a threat? The
  11. degree of threat presented
  12. by any conduct, whether
  13. legal or illegal, depends
  14. on the actions and intent
  15. of the individual and the
  16. harm they cause.
  17. $

整数のスライス

IntSlice は分割ポイントの入ったスライスを返すので、自力でもとのスライスを切り出す必要がある。

  1. origin := []int{3, 1, 4, 1, 5, 6, 5, 3, 5}
  2. indices := split.IntSlice(origin, 3, false) //=> [0 3 6 9]
  3. nPart := len(indices) - 1;
  4. result := make([][]int, nPart)
  5. // indicesを使ってもとのスライスから切り出す
  6. for i := range nPart {
  7. result[i] = origin[indices[i]:indices[i+1]]
  8. }
  9. //=> [[3 1 4 1] [5 6] [5 3 5]]

一般化

Slice は []interface{} を分割する。要素からint型の“大きさ”をとりだす関数を渡す必要がある。

  1. indices := split.Slice(
  2. slice,
  3. func(i int) int {
  4. // slice[i] の大きさを返す
  5. },
  6. 3, false
  7. )

アルゴリズム

我流。

この問題を効率よく解く既存のアルゴリズムやそれを実装したライブラリ(言語問わず)をご存知であれば教えていただけると幸いです。