将数字转换为特定范围内的等效数字

时间:2015-07-05 18:31:29

标签: algorithm swift math logic

我做某事有困难,我想将一个数字转换成它的等价物#34;在给定范围内。
虽然这个概念很简单,但很难解释,所以我会尽我所能。

让我们说你有一排无限的瓷砖,但是虽然有无数的瓷砖,但它的重复颜色模式完全相同,如下所示: A row of coloured tiles, with the same color pattern repeating again and again. Each tile has a number.

正如你所看到的,我给每个瓷砖一个数字,但是我们可以取一个范围,从0到4,然后说: 0是紫色
1是蓝色
2是红色
3是绿色
4是黄色

但是因为这种颜色模式无限重复,实际上,5将具有与0相同的颜色,6将具有与1相同的颜色,8将具有与3相同的颜色。 此外,我们不能忘记负​​数,例如,-1将具有与4相同的颜色。

实际上我想要做的是将任何给定的数字转换为我选择的范围的数量,这里的范围是[0; 4],这样我就知道这个特定的瓷砖对应的颜色。
我也希望这种方法适用于其他范围,例如,如果我的范围是[1; 5]或甚至[-7; -3],它也应该有效。

我已经找到了一个适用于[0;n]范围(n为正整数)的方法,以及a另一个正整数的方法:

convertedNumber = a % (n+1)

以下是游乐场的内容: We are doing the conversion, which behaves as expected

但它的作用只是我描述的条件,经过几个小时的努力,我仍然无法找到任何好的解决方案,使其适用于任何数字,正面或负面,以及任何范围。

不要在评论中询问更多细节。

谢谢。

3 个答案:

答案 0 :(得分:3)

func modFromRange(range: Range<Int>, ind: Int) -> Int {
  let endIndex = abs(range.endIndex.predecessor() - range.startIndex).successor()
  let i = (ind - range.startIndex) % endIndex
  return i < 0 ? (range.startIndex + i + endIndex) : (range.startIndex + i)
}

modFromRange(1...5, ind: 1)      //  1
modFromRange(-7...(-3), ind: -8) // -3

其中的作用如下:

modFromRange(-7...(-3), ind: -7) // -7
modFromRange(-7...(-3), ind: -2) // -7
modFromRange(-7...(-3), ind: -8) // -3
modFromRange(-7...(-3), ind:  1) // -4

modFromRange(1...5, ind:  1) // 1
modFromRange(1...5, ind:  5) // 5
modFromRange(1...5, ind:  6) // 1
modFromRange(1...5, ind:  0) // 5
modFromRange(1...5, ind: -1) // 4
modFromRange(1...5, ind: -9) // 1

For -7...-3:

[-10, -9, -8, -7, -6, -5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5,  6,  7]
[ -5, -4, -3, -7, -6, -5, -4, -3, -7, -6, -5, -4, -3, -7, -6, -5, -4, -3]

For 1...5:

[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[ 5,  1,  2,  3,  4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4,  5]

或者,在Swift 2上,您可以将其作为一种方法:

extension Range where T : IntegerLiteralConvertible, T : IntegerArithmeticType {
  func mod(ind: T) -> T {
    let _endIndex = {$0 >= 0 ? $0 : $0 * -1}(endIndex - startIndex)
    let i = (ind - startIndex) % _endIndex
    return i < 0 ? (startIndex + i + _endIndex) : (startIndex + i)
  }
}

哪个会像:

(1...5).mod(1) // 1
(1...5).mod(6) // 1

答案 1 :(得分:3)

你走了。该函数采用您想要映射的数字,以及范围的低值和高值,并返回范围内的值:

func mapNum(n: Int, low lo: Int, high hi: Int) -> Int {
    let spread = hi - lo + 1
    return ((n - lo) % spread + spread) % spread + lo
}

示例:

mapNum(-9, low: 0, high: 4)    // returns "1"
mapNum(-9, low: -3, high: 1)   // returns "1"
mapNum(1, low: -11, high: -7)  // returns "-9"
mapNum(3, low: -8, high: -4)   // returns "-7"
mapNum(-5, low: 4, high: 8)    // returns "5"
mapNum(-5, low: -6, high: -2)  // returns "-5"
mapNum(-9, low: -7, high: -3)  // returns "-4"

答案 2 :(得分:1)

extension Int {
    var convertedNumber: Int {
        if self < 0 {
            return  self * -4  % 5 + 1
        }
        return ( self % 5 ) + 1
    }
}
let n = -9
let result = n.convertedNumber  // 2


println(result) // 2

(-9).convertedNumber  // 2
(-8).convertedNumber  // 3
(-7).convertedNumber  // 4
(-6).convertedNumber  // 5
(-5).convertedNumber  // 1
(-4).convertedNumber  // 2
(-3).convertedNumber  // 3
(-2).convertedNumber  // 4
(-1).convertedNumber  // 5
(0).convertedNumber     // 1
(1).convertedNumber     // 2
(2).convertedNumber     // 3
(3).convertedNumber     // 4
(4).convertedNumber     // 5
(5).convertedNumber     // 1
(6).convertedNumber     // 2
(7).convertedNumber     // 3
(8).convertedNumber     // 4
(9).convertedNumber     // 5
(10).convertedNumber    // 1