У меня был ответ, и я заметил, что мне не хватало некоторых ключевых требований. Я добавил и изменил некоторые вещи для устранения этих недостающих элементов.
Основной метод не работает большую часть времени, но он делает это достаточно быстро, чтобы вы могли сделать это в цикле, пока не получите хороший ответ. В зависимости от фактических значений, в тех случаях, когда результатов очень мало, кажется, что вам нужно удачи.
шаги используются:
- Выберите случайное место для самой длинной полосы (Win в примере)
- Кронштейн полоса с потерями, чтобы предотвратить расширение его при установке объедки
- Найти индексы с достаточно последовательных слотов для удержания полосы потерь
- Выберите случайную и установите полосу потерь (возвращается, если их нет)
- Установите все остатки как
Not the value at n-1
на избегать продления или создания новой полосы
Таким образом, становится хитом или пропуском, верны ли WinCount и LossCount. Кажется, легче наткнуться, чем полосы правильного размера. Метод оболочки проверяет результат на отклонение и повтор. При заданных значениях он обычно находит победителя в первые 10 или около того раз.
Метод ядра для построения строкового представления, и помощник:
' ToDo change to return Bool() = string is easier to read
Private Function FarhamStreaks(winStrk As Int32, loseStrk As Int32, total As Int32) As String
' -1 == not set
Dim result = Enumerable.Repeat(-1, total).ToArray
' set longest streak first
Dim wNDX = RNG.Next(0, total + 1 - winStrk)
For n As Int32 = 0 To winStrk - 1
result(wNDX + n) = 1
Next
' bracket with losers so the w streak cant extend
If wNDX > 0 Then result(wNDX - 1) = 0
If wNDX + winStrk < result.Length - 1 Then result(wNDX + winStrk) = 0
' look for eligible consecutive starting slots
' might be none
Dim lossNdx As New List(Of Int32)
For n As Int32 = 0 To result.Count - 1
Dim count = CountConsecutiveLooserSlotsFrom(n, result)
If (n + 1) < result.Count AndAlso count >= loseStrk Then
lossNdx.Add(n)
End If
Next
If lossNdx.Count = 0 Then
' do over
' the code has never gotten here
' but depends on the mix of values
Return ""
End If
' set losses
Dim lNdx = lossNdx(RNG.Next(0, lossNdx.Count))
For n As Int32 = 0 To loseStrk - 1
result(lNdx + n) = 0
Next
' set the leftovers based on next value to avoid
' extending streaks
For n As Int32 = 0 To result.Length - 1
If result(n) = -1 Then
If n > 0 Then
result(n) = If(result(n - 1) = 0, 1, 0)
Else
result(n) = If(result(n + 1) = 0, 1, 0)
End If
End If
Next
Dim resultString = String.Join(",", result)
' convert to boolean
Dim realResult(total) As Boolean
For n As Int32 = 0 To total - 1
realResult(n) = Convert.ToBoolean(result(n))
Next
Return resultString
End Function
' find candidate slots for the shorter streak:
Private Function CountConsecutiveLooserSlotsFrom(ndx As Integer, theArray As Int32()) As Int32
Dim count As Int32 = 1 ' including ndx
For n As Int32 = ndx To theArray.Length - 2
If theArray(n) <> 1 AndAlso theArray(n + 1) <> 1 Then
count += 1
Else
Exit For
End If
Next
Return count
End Function
метод для проверки результата кандидата (и показатели эффективности):
Private Function MakeFarhamStreak(wins As Int32, winStreak As Int32,
lossStreak As Int32,
total As Int32) As String
Const MaxTries As Int32 = 999
Dim losses = (total - wins)
Dim reverse As Boolean = (lossStreak > winStreak)
Dim candidate As String
Dim sw As New Stopwatch
Dim pass, fail As Int32
Dim count As Int32
sw.Start()
For n As Int32 = 0 To MaxTries
If reverse Then
candidate = FarhamStreaks(lossStreak, winStreak, total)
' to do: un-reverse (Not) the results -
Else
candidate = FarhamStreaks(winStreak, lossStreak, total)
End If
Dim result = candidate.Split(","c)
' test win count
count = candidate.Where(Function(f) f = "1").Count
If count <> wins Then
fail += 1
Continue For
End If
' test loss count
count = candidate.Where(Function(f) f = "0").Count
If count <> losses Then
fail += 1
Continue For
End If
Dim tmp = candidate.Replace(","c, "")
' test win streak size
Dim wstreaks = tmp.Select(Function(c, i) tmp.Substring(i).
TakeWhile(Function(q) q = c AndAlso q = "1").
Count()).
Max
If wstreaks <> winStreak Then
fail += 1
Continue For
End If
Dim lstreaks = tmp.Select(Function(c, i) tmp.Substring(i).
TakeWhile(Function(q) q = c AndAlso q = "0").
Count()).
Max
If lstreaks <> lossStreak Then
fail += 1
Continue For
End If
pass += 1
If pass = 1 Then
Console.WriteLine("First Pass in {0}ms (try # {1} = {2})",
sw.ElapsedMilliseconds, n, candidate)
' normally, return at this point
End If
Next
End Function
Это проще чтобы соответствовать более короткой полосе вокруг более длинной, поэтому она меняет порядок ордера по мере необходимости. Не существует кода для перевода/Не результатов.
результаты:
Первый проход в 18мс (попробуйте # 4 = 1,1,1,1,1,0,0,1,0,1)
Всего FAILURES 753 75,38%
Всего Пасс 247 24,72%
Общее время 999 кандидатов 29ms
он нашел первое прохождение значения на Ьгу # 4 - с 10, 7W, 5Ws, 2LS значения обычно находит один в первом 10.
1. Что вы уже пробовали? 2. Любой язык приветствуется? Плохая идея, поскольку мы решаем только [* специальные вопросы *] (http://stackoverflow.com/help/mcve), если ваш вопрос принимает все языки, тогда нет * правильного ответа *. –
одним из способов было бы создать все комбинации выигрышей и проигрышей, а затем отфильтровать те, которые не соответствуют критериям полосы. – juharr
Должен ли я опубликовать это в Code Golf? –