Error "indices[0] = 0 not in [0,0)" when training CenterNet MobileNetV2 FPN 512x512 with tensorflow object detection api - object-detection-api

I'm running the tensorflow object detection api according to this guide https://tensorflow-object-detection-api-tutorial.readthedocs.io/en/latest/training.html#configuring-a-training-job however with a slightly modified code for making the record files and with the following system:
System information:
OS Platform and Distribution: Ubuntu 20.04.1 LTS
Python version:
TensorFlow version: 2.4.0
CUDA/cuDNN version: 11.0/8.0.5
GPU model and memory: GeForce RTX 3090, 24268 MiB
where I want to use the model CenterNet MobileNetV2 FPN 512x512 for boxes from the TensorFlow2 Detection Model Zoo (https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/tf2_detection_zoo.md).
I set up the training job according to the guide where I then run
python model_main_tf2.py --model_dir=models/my_centernet_mn_fpn --pipeline_config_path=models/my_centernet_mn_fpn/pipeline.config
and when doing this I get the following error
Traceback (most recent call last):
File "model_main_tf2.py", line 115, in <module>
tf.compat.v1.app.run()
File "/opt/anaconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/platform/app.py", line 40, in run
_run(main=main, argv=argv, flags_parser=_parse_flags_tolerate_undef)
File "/opt/anaconda3/envs/tf/lib/python3.8/site-packages/absl/app.py", line 300, in run
_run_main(main, args)
File "/opt/anaconda3/envs/tf/lib/python3.8/site-packages/absl/app.py", line 251, in _run_main
sys.exit(main(argv))
File "model_main_tf2.py", line 106, in main
model_lib_v2.train_loop(
File "/opt/anaconda3/envs/tf/lib/python3.8/site-packages/object_detection/model_lib_v2.py", line 636, in train_loop
loss = _dist_train_step(train_input_iter)
File "/opt/anaconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/eager/def_function.py", line 828, in __call__
result = self._call(*args, **kwds)
File "/opt/anaconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/eager/def_function.py", line 888, in _call
return self._stateless_fn(*args, **kwds)
File "/opt/anaconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/eager/function.py", line 2942, in __call__
return graph_function._call_flat(
File "/opt/anaconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/eager/function.py", line 1918, in _call_flat
return self._build_call_outputs(self._inference_function.call(
File "/opt/anaconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/eager/function.py", line 555, in call
outputs = execute.execute(
File "/opt/anaconda3/envs/tf/lib/python3.8/site-packages/tensorflow/python/eager/execute.py", line 59, in quick_execute
tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,
tensorflow.python.framework.errors_impl.InvalidArgumentError: 2 root error(s) found.
(0) Invalid argument: indices[0] = 0 is not in [0, 0)
[[{{node GatherV2_7}}]]
[[MultiDeviceIteratorGetNextFromShard]]
[[RemoteCall]]
[[IteratorGetNext]]
(1) Invalid argument: indices[0] = 0 is not in [0, 0)
[[{{node GatherV2_7}}]]
[[MultiDeviceIteratorGetNextFromShard]]
[[RemoteCall]]
[[IteratorGetNext]]
[[ToAbsoluteCoordinates_42/Assert/AssertGuard/branch_executed/_386/_1231]]
0 successful operations.
0 derived errors ignored. [Op:__inference__dist_train_step_54439]
Function call stack:
_dist_train_step -> _dist_train_step
When googling this error there comes some answers that the error is when creating the TFRecord files and that you need to add include_masks when creating them. However, when running the other CenterNet models from the model zoo I don't get this error so it seems strange that this would be the error.
Any ideas if it could be anything else?

Thanks for Alexandra.
Delete the keypoint association from the config file.
Original code (Delete the part marked "//delete"):
model {
center_net {
num_classes: 90
feature_extractor {
type: "mobilenet_v2_fpn_sep_conv"
}
image_resizer {
keep_aspect_ratio_resizer {
min_dimension: 512
max_dimension: 512
pad_to_max_dimension: true
}
}
use_depthwise: true
object_detection_task {
task_loss_weight: 1.0
offset_loss_weight: 1.0
scale_loss_weight: 0.1
localization_loss {
l1_localization_loss {
}
}
}
object_center_params {
object_center_loss_weight: 1.0
classification_loss {
penalty_reduced_logistic_focal_loss {
alpha: 2.0
beta: 4.0
}
}
min_box_overlap_iou: 0.7
max_box_predictions: 20
}
}
}
train_config {
batch_size: 512
data_augmentation_options { // delete
random_horizontal_flip {
keypoint_flip_permutation: 0
keypoint_flip_permutation: 2
keypoint_flip_permutation: 1
keypoint_flip_permutation: 4
keypoint_flip_permutation: 3
keypoint_flip_permutation: 6
keypoint_flip_permutation: 5
keypoint_flip_permutation: 8
keypoint_flip_permutation: 7
keypoint_flip_permutation: 10
keypoint_flip_permutation: 9
keypoint_flip_permutation: 12
keypoint_flip_permutation: 11
keypoint_flip_permutation: 14
keypoint_flip_permutation: 13
keypoint_flip_permutation: 16
keypoint_flip_permutation: 15
}
} // delete
data_augmentation_options {
random_patch_gaussian {
}
}
data_augmentation_options {
random_crop_image {
min_aspect_ratio: 0.5
max_aspect_ratio: 1.7
random_coef: 0.25
}
}
data_augmentation_options {
random_adjust_hue {
}
}
data_augmentation_options {
random_adjust_contrast {
}
}
data_augmentation_options {
random_adjust_saturation {
}
}
data_augmentation_options {
random_adjust_brightness {
}
}
data_augmentation_options {
random_absolute_pad_image {
max_height_padding: 200
max_width_padding: 200
pad_color: 0.0
pad_color: 0.0
pad_color: 0.0
}
}
optimizer {
adam_optimizer {
learning_rate {
cosine_decay_learning_rate {
learning_rate_base: 5e-3
total_steps: 300000
warmup_learning_rate: 1e-4
warmup_steps: 5000
}
}
}
use_moving_average: false
}
num_steps: 300000
max_number_of_boxes: 100
unpad_groundtruth_tensors: false
fine_tune_checkpoint_type: ""
}
train_input_reader {
label_map_path: "PATH_TO_BE_CONFIGURED/label_map.txt"
tf_record_input_reader {
input_path: "PATH_TO_BE_CONFIGURED/train2017-?????-of-00256.tfrecord"
}
filenames_shuffle_buffer_size: 256
num_keypoints: 17 // delete
}
eval_config {
num_visualizations: 10
metrics_set: "coco_detection_metrics"
use_moving_averages: false
min_score_threshold: 0.20000000298023224
max_num_boxes_to_visualize: 20
batch_size: 1
}
eval_input_reader {
label_map_path: "PATH_TO_BE_CONFIGURED/label_map.txt"
shuffle: false
num_epochs: 1
tf_record_input_reader {
input_path: "PATH_TO_BE_CONFIGURED/val2017-?????-of-00032.tfrecord"
}
num_keypoints: 17 // delete
}
The code below is how i worked (modified):
model {
center_net {
num_classes: 4
feature_extractor {
type: "mobilenet_v2_fpn_sep_conv"
}
image_resizer {
keep_aspect_ratio_resizer {
min_dimension: 512
max_dimension: 512
pad_to_max_dimension: true
}
}
use_depthwise: true
object_detection_task {
task_loss_weight: 1.0
offset_loss_weight: 1.0
scale_loss_weight: 0.1
localization_loss {
l1_localization_loss {
}
}
}
object_center_params {
object_center_loss_weight: 1.0
classification_loss {
penalty_reduced_logistic_focal_loss {
alpha: 2.0
beta: 4.0
}
}
min_box_overlap_iou: 0.7
max_box_predictions: 20
}
}
}
train_config {
batch_size: 8
data_augmentation_options {
random_patch_gaussian {
}
}
data_augmentation_options {
random_crop_image {
min_aspect_ratio: 0.5
max_aspect_ratio: 1.7
random_coef: 0.25
}
}
data_augmentation_options {
random_adjust_hue {
}
}
data_augmentation_options {
random_adjust_contrast {
}
}
data_augmentation_options {
random_adjust_saturation {
}
}
data_augmentation_options {
random_adjust_brightness {
}
}
data_augmentation_options {
random_absolute_pad_image {
max_height_padding: 200
max_width_padding: 200
pad_color: 0.0
pad_color: 0.0
pad_color: 0.0
}
}
optimizer {
adam_optimizer {
learning_rate {
cosine_decay_learning_rate {
learning_rate_base: 5e-3
total_steps: 50000
warmup_learning_rate: 1e-4
warmup_steps: 2000
}
}
}
use_moving_average: false
}
num_steps: 6000
max_number_of_boxes: 4
unpad_groundtruth_tensors: false
fine_tune_checkpoint_version: V2
fine_tune_checkpoint: "pre-trained-models/centernet_mobilenetv2_fpn_od/checkpoint/ckpt-301"
fine_tune_checkpoint_type: "detection"
}
train_input_reader {
label_map_path: "annotations/label_map.pbtxt"
tf_record_input_reader {
input_path: "annotations/train_c.record"
}
filenames_shuffle_buffer_size: 256
}
eval_config {
num_visualizations: 10
metrics_set: "coco_detection_metrics"
use_moving_averages: false
min_score_threshold: 0.20000000298023224
max_num_boxes_to_visualize: 20
batch_size: 1
}
eval_input_reader {
label_map_path: "annotations/label_map.pbtxt"
shuffle: false
num_epochs: 1
tf_record_input_reader {
input_path: "annotations/test_c.record"
}
}

Related

Swift function returning wrong output

I created a function that prints where the students are - lesson, long break or short break (and which short break)
Function parameters are:
shortBreak - duration of short break
longBreak - duration of long break
lesson - after which lesson is long break
time - the time where students are located
My parameters to test function are
currently(shortBreak: 5, longBreak: 15, lesson: 3, time: "10:37)
So it should be
8:00 - 8:45 - lesson
8:45 - 8:50 - short break
8:50 - 9:35 - lesson
9:35 - 9:40 - short break
9:40 - 10:25 - lesson
10:25 - 10:40 - long break (after 3.lesson is long break)
which means that students are currenty on long break, but my output says that they are on lesson.
I've reviewed the code again, but I can't find where I'm wrong.
Also, is there better way to manipulate with time paramater?
import UIKit
enum current {
case lesson
case shortBreak
case longBreak
}
func currently(shortBreak: Int, longBreak: Int, lesson: Int, time:String){
var shortBreakCounter: Int = 0
var currentLesson: Int = 1
var currentHours: Int = 8
var currentMinute: Int = 0
var currentCase: current = .lesson
let minute: Int = Int(time.suffix(2)) ?? 0
let hour: Int = Int(time.prefix(2)) ?? 0
if(checkValid(hour: hour, minute: minute)){
print("Invalid time")
}
else {
while isInRange(hour: currentHours, minute: currentMinute) {
currentCase = .lesson
currentMinute += 45
if currentMinute >= 60 {
currentHours += 1
currentMinute = 0
}
if currentLesson == lesson {
currentCase = .longBreak
currentMinute += longBreak
if currentMinute >= 60 {
currentHours += 1
currentMinute = 0
}
} else{
currentCase = .shortBreak
currentMinute += shortBreak
shortBreakCounter += 1
if currentMinute >= 60 {
currentHours += 1
currentMinute = 0
}
}
currentLesson += 1
}
switch currentCase {
case .shortBreak:
print("Students are on \(shortBreakCounter) short break")
case .longBreak:
print("Students are on long break")
default:
print("Students are on lesson")
}
}
}
func checkValid(hour: Int, minute:Int) -> Bool {
if hour >= 16 || hour < 8 {
return true
} else if minute > 59 || minute < 0 {
return true
}
return false
}
func isInRange(hour: Int, minute: Int) -> Bool{
if 8..<16 ~= hour && 0..<60 ~= minute {
return false
}
return true
}
currently(shortBreak: 5, longBreak: 15, lesson: 3, time: "10:37")
if currentMinute >= 60 {
currentHours += 1
currentMinute = 0
}
This is wrong, you should set currentMinute to the current value - 60.
Imagine if the value is 75, there are 15 minutes that is gone because you set it as 0.
it should be
if currentMinute >= 60 {
currentHours += 1
currentMinute = currentMinute - 60
}
isInRange always returns false if checkValid is true. You are always getting the default currentCase (lesson).
A better way to "edit the time parameter" is by using Date.

MT4/MQL4 EA Modification erro

I have an MT4 EA, trying to modify it, I'll share the part I need to modify it below:
void exit()
{
for(int i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
{
if(OrderProfit()<0) //LOSS
{
amountloss=amountloss+OrderProfit();
TotalLotLoss=TotalLotLoss+OrderLots();
lot=lots;
wincount=0;
}
else //profit
{
if(wincount==0)
{
TotalLotLoss=TotalLotLoss+OrderLots();
amountloss=amountloss+OrderProfit();
lot=TotalLotLoss*multi;
wincount=1;
}
else
{
TotalLotLoss=TotalLotLoss+OrderLots();
amountloss=amountloss+OrderProfit();
if(amountloss>0)
{
TotalLotLoss=0;
amountloss=0;
lot=lots;
}
else
{
lot=OrderLots();
}
After 1 win it duplicate all losses by 2 and keep doing this until all losses are recovered, what I want is after 1 recovering win, reset to 0.01
I will give you example:
0.01 loss
0.01 loss
0.01 loss
0.01 loss
0.01 win
0.04 win
then reset to 0.01
that's all
I couldn't figure how to do it! any help?

In Swift, outwards pingpong sequence?

Say you have
for i in 0 ... 10 {
print(i)
}
of course it will print 0,1,2,3,4,5,6,7,8,9,10
for i in 0 ..< 5 {
that's 0,1,2,3,4.
I want to start at a certain integer and pingpong outwards over the count of numbers
So,
for i in function or something (10, 3)
that's 3 4 2 5 1 6 0 7 8 9
for i in function or something (10, 8) {
would be 8 9 7 6 5 4 3 2 1 0
for i in function or something (10, 2) {
would be 2 3 1 4 0 5 6 7 8 9
So it's just an outwards pingpong.
What should I type where I have written function or something (10, 2)?
There might be some really cool syntax possible, along the lines 0 # 7 # 10.
What about something like (0..<10).outPong(3)?
How to formulate such a sequence?
Here's a naive example of how you'd do an outwards pingpong, at the call level.
Call exampleLoad for each of the items in RA, outwards pingpoing:
func loadItemsPongwise(startWith: Int) {
// RA = ... this is your array of some type
exampleLoad(startWith)
let k = RA.count
var howManyDone: Int = 0
var distance: Int = 1
while howManyDone < ( k - 1 ) {
let tryRight = alreadyLoaded + distance
if tryRight < k {
howManyDone = howManyDone + 1
exampleLoad(RA[tryRight])
}
let tryLeft = alreadyLoaded - distance
if tryLeft >= 0 {
howManyDone = howManyDone + 1
exampleLoad(RA[tryLeft])
}
distance = distance + 1
}
}
Of course, something like this wouild be much nicer:
func loadItemsPongwise(startWith: Int) {
for i in ???? {
exampleLoad(i)
}
}
public extension ClosedRange where Bound: AdditiveArithmetic {
func 🏓(
by contiguousAdvancement: Bound,
startingAt start: Bound
) -> AnySequence<Bound> {
guard contains(start)
else { return .init( EmptyCollection() ) }
var advancement = contiguousAdvancement
typealias Operate = (Bound, Bound) -> Bound
var pingPong: Operate = (+)
var contiguouslyAdvance: Operate = (-)
return .init(
sequence(first: start) { previous in
pingPongIterate: do {
defer { advancement += contiguousAdvancement }
let pingPonged = pingPong(previous, advancement)
guard self.contains(pingPonged)
else { break pingPongIterate }
(pingPong, contiguouslyAdvance) = (contiguouslyAdvance, pingPong)
return pingPonged
}
let contiguouslyAdvanced = contiguouslyAdvance(previous, contiguousAdvancement)
return self.contains(contiguouslyAdvanced)
? contiguouslyAdvanced
: nil
}
)
}
}
public extension ClosedRange where Bound: AdditiveArithmetic & ExpressibleByIntegerLiteral {
func 🏓(startingAt start: Bound) -> AnySequence<Bound> {
🏓(by: 1, startingAt: start)
}
}
public extension ClosedRange where Bound: BinaryInteger {
func 🏓(by contiguousAdvancement: Bound = 1) -> AnySequence<Bound> {
🏓(by: contiguousAdvancement, startingAt: (upperBound + lowerBound) / 2)
}
}
public extension ClosedRange where Bound: FloatingPoint {
func 🏓(by contiguousAdvancement: Bound = 1) -> AnySequence<Bound> {
🏓(by: contiguousAdvancement, startingAt: (upperBound + lowerBound) / 2)
}
}
XCTAssertEqual(
Array( (2...10).🏓() ),
[6, 7, 5, 8, 4, 9, 3, 10, 2]
)
XCTAssertEqual(
Array( (2...10).🏓(startingAt: 7) ),
[7, 8, 6, 9, 5, 10, 4, 3, 2]
)
XCTAssertEqual(
Array( (-1.5...7.5).🏓(by: 1.5) ),
[3, 4.5, 1.5, 6, 0, 7.5, -1.5]
)
XCTAssertEqual(
Array( (0...6).🏓(by: -1) ),
[3, 2, 4, 1, 5, 0, 6]
)
XCTAssertEqual(
Array( (0...3).🏓(startingAt: 4) ),
[]
)
So I went the route of taking the analogy of ping-pong seriously. I left some comments for clarity.
It simulates an actual ping pong ball bouncing (starting from the net, oddly), back and forth on a ping pong table that has a net that might not be centered. If it's about to go off the edge on one side, then it just goes to the other side and I like to imagine it does smaller and smaller bounces until it rolls off the table.
Here's the code with comments and a test:
// It's supposed to be a ping pong table 🤷‍♂️
struct 🟦: IteratorProtocol, Sequence {
typealias Element = Int
// The table *is* the iterator
typealias Iterator = 🟦
let leftEdgePosition: Int
/// The starting point for the ball
let netPosition: Int
let rightEdgePosition: Int
/// For convenience in checking whether different ball positions are on the table.
private let tableBounds: ClosedRange<Int>
init(leftEdgePosition: Int, netPosition: Int, rightEdgePosition: Int) {
self.leftEdgePosition = leftEdgePosition
self.netPosition = netPosition
self.rightEdgePosition = rightEdgePosition
self.tableBounds = leftEdgePosition...rightEdgePosition
}
private var distanceFromNet = 0
/// The side of the table the ping pong ball is headed toward
private var ballDirection: PingPongBallDirection = .towardLeftEdge
func makeIterator() -> 🟦 {
return self
}
/// This gets called for each iteration in the for loop. Once the ball goes beyond the table, we should return nil to stop the for loop.
mutating public func next() -> Int? {
// the ball position we will return if this position is on the table
let ballPosition = ballDirection.locationCalculator(netPosition, distanceFromNet)
// the ball position we will return if the first ball position is not on the table
let redirectedPosition = (!ballDirection).locationCalculator(netPosition, distanceFromNet)
// determine which ball position to return and set up our state for the next call to next()
var ballPositionToReturn: Int?
if tableBounds.contains(ballPosition) {
ballPositionToReturn = ballPosition
let ballMirrorPosition = (!ballDirection).locationCalculator(netPosition, distanceFromNet)
let ballIsTrailingOff = !tableBounds.contains(ballMirrorPosition)
if !ballIsTrailingOff {
// switch the direction because the ball hit the table
ballDirection = !ballDirection
}
// If we're heading to the right, i.e 3 -> 4 in the case of 0 << 3 >> 10, then increase
// the distance from the net.
// If we're trailing off and not ping-ponging any more, then we need to add distance.
if ballDirection == .towardRightEdge || ballIsTrailingOff {
distanceFromNet += 1
}
} else if tableBounds.contains(redirectedPosition) {
ballPositionToReturn = redirectedPosition
// reflect the redirection
ballDirection = !ballDirection
// add distance when we redirect
distanceFromNet += 1
}
return ballPositionToReturn
}
}
enum PingPongBallDirection {
case towardLeftEdge
case towardRightEdge
/// Returns the oppposite direction
static prefix func !(direction: PingPongBallDirection) -> PingPongBallDirection {
switch direction {
case towardLeftEdge: return towardRightEdge
case towardRightEdge: return towardLeftEdge
}
}
// In our world, right is greater and left is lesser.
var locationCalculator: (Int, Int) -> Int {
switch self {
case .towardLeftEdge: return (-)
case .towardRightEdge: return (+)
}
}
}
// Make the syntax work
precedencegroup PingPongPrecedenceGroup {
associativity: left
// this makes sure the ping pong operator gets evaluated before the assignment operator
higherThan: AssignmentPrecedence
}
infix operator ...: PingPongPrecedenceGroup
func ... (lhs: ClosedRange<Int>, rhs: Int) -> 🟦 {
return 🟦(leftEdgePosition: lhs.lowerBound, netPosition: lhs.upperBound, rightEdgePosition: rhs)
}
for i in 0...10 {
for j in 0...i...10 {
print(j, terminator: " ")
}
print()
}
// OUTPUT:
// 0 1 2 3 4 5 6 7 8 9 10
// 1 2 0 3 4 5 6 7 8 9 10
// 2 3 1 4 0 5 6 7 8 9 10
// 3 4 2 5 1 6 0 7 8 9 10
// 4 5 3 6 2 7 1 8 0 9 10
// 5 6 4 7 3 8 2 9 1 10 0
// 6 7 5 8 4 9 3 10 2 1 0
// 7 8 6 9 5 10 4 3 2 1 0
// 8 9 7 10 6 5 4 3 2 1 0
// 9 10 8 7 6 5 4 3 2 1 0
// 10 9 8 7 6 5 4 3 2 1 0
stateless
Just for anyone working on the syntax.
I wasted an hour of my life figuring out a stateless conversion.
(I couldn't make it simple or elegant - maybe someone else can!)
var plaground = "directly convert a single ping pong index to a plain index"
let L: Int = 10
let S: Int = 7
func ppiToIndex(_ ppi: Int) -> Int {
let inner = S+1 < (L-S) ? (S+1) : (L-S)
let pp = (ppi+1) / ( (ppi % 2 == 1) ? 2 : -2 )
let way = (S < L/2) ? -(inner-ppi-1) : (inner-ppi-1)
return (ppi < inner*2-1) ? S+pp : S+way
}
for i in 0..<L {
print(" \(i) \(ppiToIndex(i)) ")
}
inner is how many from the start inclusive to the nearer end inclusive.
pp is a full-on endless ping pong.
way is the correct direction +/- to add once you pass the inner area.
Think of how you'd do this with a deck of cards, or a set of matchsticks. Just split the series into two at the point where you want to start, reverse the order of one of the resulting series, and alternate pulling values off the two series.
Here's a utility that alternates between two series until both are exhausted:
func alternateUntilBothAreExhausted<T> (arr1:Array<T>, arr2:Array<T>)
-> Array<T> {
var result = Array<T>()
var arr1 = arr1; var arr2 = arr2
while true {
if let last1 = arr1.popLast() {
result.append(last1)
}
if let last2 = arr2.popLast() {
result.append(last2)
}
if arr1.isEmpty && arr2.isEmpty {
return result
}
}
}
So we start with one series, split it, reverse one, and alternate:
func pingPong<T>(array:Array<T>, startingAtIndex ix:Int) -> Array<T> {
let arr1 = array[..<ix]
let arr2 = array[ix...]
return alternateUntilBothAreExhausted(
arr1: Array(arr1), arr2: Array(arr2.reversed()))
}
Example:
let ping = pingPong(array: Array(0..<10), startingAtIndex:4)
// [3, 4, 2, 5, 1, 6, 0, 7, 8, 9]
Wrapping that up in your desired syntax is trivial and is left as an exercise for the reader.

Hackerrank New Year Chaos Swift

I am trying to solve Hackerrank's New Year Chaos problem in Swift. https://www.hackerrank.com/challenges/new-year-chaos/problem
It is about finding the number of bribes people made on a line waiting for a roller coaster ride. For example, there is a total of 3 bribes in this list [2, 1, 5, 3, 4].
Person 2 bribed person 1.
Person 5 bribed person 3 and 4.
If there are more than 2 bribes by a person, the line becomes "Too chaotic".
I was able to get an exponential solution. However, I want to make it linear.
func minimumBribes(q: [Int]) -> Void {
var bribeCount = 0
var chaotic = false
// for i in 0..<q.count {
// if q[i] - (i + 1) > 2 {
// chaotic = true
// break
// }
//
// for j in i + 1..<q.count {
// if q[i] > q[j] {
// bribeCount += 1
// }
// }
// }
var i = 0
while i < q.count - 1 {
if q[i] - (i + 1) > 2 {
chaotic = true
break
} else if q[i] > i + 1 {
bribeCount += (q[i] - (i + 1))
i += 1
} else if q[i] <= i + 1 && q[i] > q[i + 1] && q.indices.contains(i + 1) {
bribeCount += 1
i += 1
} else { // q[i] < q[i + 1]
i += 1
}
}
if chaotic {
print("Too chaotic")
} else {
print(bribeCount)
}
}
I commented out the exponential solution, which works. But the linear solution does not work and I cannot find out why. It works with the following arrays, [3,2,1,6,5,4], [2,5,1,3,4], [1,2,5,3,7,8,6,4], [1,3,4,2,7,6,5,9,8,11,10,14,13,12].
But there is a really long array in one of the test cases of the problem, which I do not get the correct answer with my linear solution.
For this long array, I get 966 with my exponential solution but the linear solution prints 905.
[2,1,5,6,3,4,9,8,11,7,10,14,13,12,17,16,15,19,18,22,20,24,23,21,27,28,25,26,30,29,33,32,31,35,36,34,39,38,37,42,40,44,41,43,47,46,48,45,50,52,49,51,54,56,55,53,59,58,57,61,63,60,65,64,67,68,62,69,66,72,70,74,73,71,77,75,79,78,81,82,80,76,85,84,83,86,89,90,88,87,92,91,95,94,93,98,97,100,96,102,99,104,101,105,103,108,106,109,107,112,111,110,113,116,114,118,119,117,115,122,121,120,124,123,127,125,126,130,129,128,131,133,135,136,132,134,139,140,138,137,143,141,144,146,145,142,148,150,147,149,153,152,155,151,157,154,158,159,156,161,160,164,165,163,167,166,162,170,171,172,168,169,175,173,174,177,176,180,181,178,179,183,182,184,187,188,185,190,189,186,191,194,192,196,197,195,199,193,198,202,200,204,205,203,207,206,201,210,209,211,208,214,215,216,212,218,217,220,213,222,219,224,221,223,227,226,225,230,231,229,228,234,235,233,237,232,239,236,241,238,240,243,242,246,245,248,249,250,247,244,253,252,251,256,255,258,254,257,259,261,262,263,265,264,260,268,266,267,271,270,273,269,274,272,275,278,276,279,277,282,283,280,281,286,284,288,287,290,289,285,293,291,292,296,294,298,297,299,295,302,301,304,303,306,300,305,309,308,307,312,311,314,315,313,310,316,319,318,321,320,317,324,325,322,323,328,327,330,326,332,331,329,335,334,333,336,338,337,341,340,339,344,343,342,347,345,349,346,351,350,348,353,355,352,357,358,354,356,359,361,360,364,362,366,365,363,368,370,367,371,372,369,374,373,376,375,378,379,377,382,381,383,380,386,387,384,385,390,388,392,391,389,393,396,397,394,398,395,401,400,403,402,399,405,407,406,409,408,411,410,404,413,412,415,417,416,414,420,419,422,421,418,424,426,423,425,428,427,431,430,429,434,435,436,437,432,433,440,438,439,443,441,445,442,447,444,448,446,449,452,451,450,455,453,454,457,456,460,459,458,463,462,464,461,467,465,466,470,469,472,468,474,471,475,473,477,476,480,479,478,483,482,485,481,487,484,489,490,491,488,492,486,494,495,496,498,493,500,499,497,502,504,501,503,507,506,505,509,511,508,513,510,512,514,516,518,519,515,521,522,520,524,517,523,525,526,529,527,531,528,533,532,534,530,537,536,539,535,541,538,540,543,544,542,547,548,545,549,546,552,550,551,554,553,557,555,556,560,559,558,563,562,564,561,567,568,566,565,569,572,571,570,575,574,577,576,579,573,580,578,583,581,584,582,587,586,585,590,589,588,593,594,592,595,591,598,599,596,597,602,603,604,605,600,601,608,609,607,611,612,606,610,615,616,614,613,619,618,617,622,620,624,621,626,625,623,628,627,631,630,633,629,635,632,637,636,634,638,640,642,639,641,645,644,647,643,646,650,648,652,653,654,649,651,656,658,657,655,661,659,660,663,664,666,662,668,667,670,665,671,673,669,672,676,677,674,679,675,680,678,681,684,682,686,685,683,689,690,688,687,693,692,691,696,695,698,694,700,701,702,697,704,699,706,703,705,709,707,711,712,710,708,713,716,715,714,718,720,721,719,723,717,722,726,725,724,729,728,727,730,733,732,735,734,736,731,738,737,741,739,740,744,743,742,747,746,745,750,748,752,749,753,751,756,754,758,755,757,761,760,759,764,763,762,767,765,768,766,771,770,769,774,773,776,772,778,777,779,775,781,780,783,784,782,786,788,789,787,790,785,793,791,792,796,795,794,798,797,801,799,803,800,805,802,804,808,806,807,811,809,810,814,812,813,817,816,819,818,815,820,821,823,822,824,826,827,825,828,831,829,830,834,833,836,832,837,839,838,841,835,840,844,842,846,845,843,849,847,851,850,852,848,855,854,853,857,856,858,861,862,860,859,863,866,865,864,867,870,869,868,872,874,875,871,873,877,878,876,880,881,879,884,883,885,882,888,886,890,891,889,893,887,895,892,896,898,894,899,897,902,901,903,905,900,904,908,907,910,909,906,912,911,915,913,916,918,914,919,921,917,923,920,924,922,927,925,929,928,926,932,931,934,930,933,935,937,939,940,938,936,943,944,942,941,947,946,948,945,951,950,949,953,952,956,954,958,957,955,961,962,963,959,964,966,960,965,969,968,971,967,970,974,972,976,973,975,979,977,981,982,978,980,983,986,984,985,989,988,987,990,993,991,995,994,997,992,999,1000,996,998]
Please help me figure out what is wrong with my solution. Thanks in advance!!
Here is my solution which passes all the test cases :)
func minimumBribes(q: [Int]) -> Void {
var bCount = 0
var isChaotic = false
for (key,value) in q.enumerated() {
if (value - 1) - key > 2 {
isChaotic = true
break
}
for index in stride(from: max(0, value - 2), to: key, by: 1){
if q[index] > value {
bCount += 1
}
}
}
isChaotic ? print("Too chaotic") : print("\(bCount)")
}
What you basically need to do is to first check if the element in each loop is on it's correct position. And if not you find out how much further is it from the right position if its greater than 2 you print "Too chaotic". Your solution is correct uptil this point. But if the difference is less than or equal to 2 then you need to increment the bribes and swap the indices to represent updated array. Furthermore if there are two swaps then you need to represent how the array would be effected by these 2 swaps and hence swap these values before the next iteration to ensure the array is in the condition it would be after these swaps.
Please refer to my solution below. It passes for all test cases:
func swapValues( arr:inout [Int],index:Int, times: Int, bribes:inout Int) -> Bool {
if times == 0 {
return false
}
if arr[index] > arr[index+1] {
let temp = arr[index+1]
arr[index+1] = arr[index]
arr[index] = temp
bribes = bribes + 1
return swapValues(arr: &arr, index: index+1, times: times-1,bribes: &bribes)
}else{
var diff = abs(arr[index+1] - (index+2))
if diff > 2 {
print("Too chaotic")
return true
}
var tooChaotic = swapValues(arr: &arr, index: index+1, times: diff,bribes:&bribes)
if tooChaotic {
return true
}
return swapValues(arr: &arr, index: index, times: times, bribes: &bribes)
}
}
func minimumBribes(q: [Int]) -> Void {
var qC = q
var bribes = 0
var i = 0
while i <= qC.count-1{
if i+1 == qC[i] {
i = i + 1
continue
}
let diff = abs(qC[i] - (i+1))
if diff > 2 {
print("Too chaotic")
return
}
var tooChaotic = swapValues(arr: &qC, index: i, times: diff, bribes: &bribes)
if tooChaotic {
return
}
}
print(bribes)
}
I found this short and easy solution.
func minimumBribes(q: [Int]) -> Void {
var ans = 0
var shouldShow = true
for i in stride(from: (q.count - 1), through: 0, by: -1) {
if (q[i] - (i+1) > 2) {
shouldShow = false
break;
}
for j in stride(from: max(0, q[i] - 2), to: i, by: 1){
if q[j] > q[i] {
ans += 1
}
}
}
if shouldShow {
print(ans)
} else {
print("Too chaotic")
} }
https://github.com/AnanthaKrish/example-ios-apps

Rotating around completely in 90 degree intervals

I have a circular menu that rotates 90 degrees every time leftArrow_mc is clicked but at 270 degrees the button stops working. Also will the reseting the degrees back to 0 do anything for me?
import com.greensock.*;
import com.greensock.easing.*;
leftArrow_mc.addEventListener(MouseEvent.CLICK, rotateLeft1);
function rotateLeft1(event: MouseEvent):void {
if (bottomWheel_menu_mc.rotation==0) {
TweenLite.to(bottomWheel_menu_mc, 1, {rotation: 90, ease:Bounce.easeOut});
} else if (bottomWheel_menu_mc.rotation == 90) {
TweenLite.to(bottomWheel_menu_mc, 1, {rotation: 180, ease:Bounce.easeOut});
} else if (bottomWheel_menu_mc.rotation == 180) {
TweenLite.to(bottomWheel_menu_mc, 1, {rotation: 270, ease:Bounce.easeOut});
} else if (bottomWheel_menu_mc.rotation == 270) {
TweenLite.to(bottomWheel_menu_mc, 1, {rotation: 360, ease:Bounce.easeOut});
}
else if (bottomWheel_menu_mc.rotation == 360) {
bottomWheel_menu_mc.rotation == 0
}
}
heres your answer, it works.. If you need the working let me know..its late so im not sure why this behaves like it does but i would check into the property (rotation:) inside your tweens.
import com.greensock.*;
import com.greensock.easing.*;
leftArrow_mc.addEventListener(MouseEvent.CLICK, rotateLeft1);
function rotateLeft1(event: MouseEvent):void {
if (bottomWheel_menu_mc.rotation==0) {
TweenLite.to(bottomWheel_menu_mc, 1, {rotation: 90, ease:Bounce.easeOut});
} else if (bottomWheel_menu_mc.rotation == 90) {
TweenLite.to(bottomWheel_menu_mc, 1, {rotation: 180, ease:Bounce.easeOut});
} else if (bottomWheel_menu_mc.rotation == 180) {
TweenLite.to(bottomWheel_menu_mc, 1, {rotation: 270, ease:Bounce.easeOut});
} else if (bottomWheel_menu_mc.rotation == -90) {
TweenLite.to(bottomWheel_menu_mc, 1, {rotation: 0, ease:Bounce.easeOut});
}
trace( bottomWheel_menu_mc.rotation);
}

Resources