2016-05-28 13 views
1

У меня есть колесо цвета, которое отображает цвет каждого часа на 24-часовом часах. Теперь, учитывая час дня, я хочу сопоставить эти цвета с 12-часовыми часами, так что цвета за 5 часов до и через 6 часов после текущего часа. Но это становится немного сложным b/c, 0-й индекс результата всегда должен быть 0-го цвета или 12-го цвета 24-цветного колеса.Ошибка модуля Modulo

Например, учитывая colors24 как массив из 24 цветов и часовое время 5, то конечный color12 массива будет отображаться на индексы colors24 как:

{0,1,2,3,4,5,6,7,8,9,10,11} 

Если час 3, то:

{0,1,2,3,4,5,6,7,8,9,22,23} 

А если час 9, то:

{12,13,14,15,4,5,6,7,8,9,10,11} 

в если алгоритм может быть обобщен на любые два массива, независимо от их размера, если первый равномерно делится на второй.

ответ

2

Если hours это общее количество часов (24), length количество цветов (12), а hour - текущий час, то это общий алгоритм для получения индекса EXEs в цвете массив:

result = []; 
add = hour + hours - (length/2) - (length % 2) + 1; 
for (i = 0; i < length; i++) { 
    result[(add + i) % length] = (add + i) % hours; 
} 

Вот реализация JavaScript (общая, может быть использован с другими диапазонами, чем 24/12):

function getColorIndexes(hour, hours, length) { 
 
    var i, result, add; 
 

 
    if (hours % length) throw "number of hours must be multiple of length"; 
 
    result = []; 
 
    add = hour + hours - (length/2) - (length % 2) + 1; 
 
    for (i = 0; i < length; i++) { 
 
     result[(add + i) % length] = (add + i) % hours; 
 
    } 
 
    return result; 
 
} 
 

 
console.log ('hour=3: ' + getColorIndexes(3, 24, 12)); 
 
console.log ('hour=5: ' + getColorIndexes(5, 24, 12)); 
 
console.log ('hour=9: ' + getColorIndexes(9, 24, 12)); 
 
console.log ('hour=23: ' + getColorIndexes(23, 24, 12));

Как указан в вопрос, количество часов (24) должно быть кратным длине возвращаемого массива.

+0

Удивительно! Я знал, что должно быть кратким решением, но я просто не мог понять. Спасибо, отмечен как правильный ответ. – trans

+0

Извините за задержку. Я попал в другие части своего приложения и только что вернулся к этому. Спасибо за этот ответ. Я впечатлен. Это был вызов для вас или просто пришел к вам прямо сейчас? – trans

0

Не могли бы вы сразу получить цвета, то есть от (C-Y/2 + X + 1)% X до (C + Y/2)% X, а затем отсортировать их?

(Это то же самое, как цикл (C + Z + X + 1)% X от Z = -Y/2 до Z = Y/2-1):

for (i = 0, j = c+x+1, z = -y/2; z < y/2; z++) { 
    color[i++] = (z+j)%x; 
} 

Для C = 3 , X = 24 и Y = 12, вы получите:

(C-12/2+24+1)%24 = 3-6+24+1 = 22, 23, 0, 1 .. 9 

После сортировки вы получите 0, 1 ... 9, 22, 23 в соответствии с просьбой.

Без сортировки вы всегда получаете последовательность с текущим часовым посещением посередине (что может быть полезно для некоторых приложений), в то время как ваш 3-й пример сдвигает влево два места.

Вы можете сделать это, переключившись вместо сортировки, заметив, что вам нужно только сдвинуть, если c ниже Y/2 (C = 3 заставляет вас начинать с -2, что становится 22), и в этом случае вы меняете на отрицательный y/2-c (здесь, 2 или 12 + 2 с использованием другого модуля), или если c> (xy/2), и в этом случае вы закончите выше x: если c = 20, c + 6 - 26 , который получает откат до 2:

15 16 17 18 19 20 21 22 23 0 1 2 

и дает как фактор 2 + 1 = 3, или (с + у/2)% х + 1 в целом:

0 1 2 15 16 17 18 19 20 21 22 23 


for (i = 0, j = c+x+1, z = -y/2; z < y/2; z++) { 
    color[(s+i++)%y] = (z+j)%x; 
} 

Однако, Я думаю, что у вас проблема, если x > 2 * y; в этом случае вы получаете некоторые значения c, для которых ни 0, ни x/2 не находятся в досягаемости c. То есть «равномерно делимый» должен означать, что x всегда должен быть равным до y * 2.

1

Это можно сделать, предварительно поместив числа во временный массив, затем найдя в нем место 0 или 12 и распечатав результаты с этой позиции, обрабатывая индекс как круговой (т.по модулю длина массива)

Ниже приведен пример реализации:

int num[12]; 
// Populate the values that we are going to need 
for (int i = 0 ; i != 12 ; i++) { 
    // 19 is 24-5 
    num[i] = (h+i+19) % 24; 
} 
int p = 0; 
// Find p, the position of 0 or 12 
while (num[p] != 0 && num[p] != 12) { 
    p++; 
} 
// Print num[] array with offset of p 
for (int i = 0 ; i != 12 ; i++) { 
    printf("%d ", num[(p+i) % 12]); 
} 

Demo.

Примечание: первый и второй циклы могут быть объединены. Добавьте проверку, если номер, который вы только что установили, равен нулю или 12, и установите значение p, когда найдете совпадение.

+0

Это в основном то, как я тоже закончил работу (вскоре после того, как я разместил вопрос). Но я знал, что должен быть более прямой путь. – trans

0

Вот решение в JavaScript:

function f(h) { 
    var retval = []; 
    for (var i = h - 5; i <= h + 6; ++i) 
    retval.push((i+24) % 24); 
    return retval.sort(function(a,b){return a-b;}); // This is just a regular sort 
} 

https://repl.it/CWQf

Например,

f(5) // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] 
f(3) // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 22, 23 ] 
f(9) // [ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ] 
+1

Вопрос гласит: 'f (9)' должно быть чем-то другим. –

+0

@ н.м. Те же номера, разные порядки. Из вопроса было неясно, имеет ли значение порядок; в этом решении он всегда сортируется. – Matt