Программа Ruby Проверка числа Капрекара

Я пытаюсь сделать немного кода, который будет проверять, является ли число числом Капрекара. Я огляделся, чтобы посмотреть, не поднимал ли кто-нибудь эту тему, но не нашел достаточной информации, поэтому приношу вам свои горести.

Что такое число Капрекара:

Для числа Капрекара k с n цифрами, если вы возведете его в квадрат и добавите правые n цифр к левым n или n-1 цифрам, результирующая сумма будет равна k. 9 является примером этого, поскольку 9^2=81, а 8+1=9.

Вот что я собрал прямо сейчас:

def kaprekar?(k)

  if k**2.to_s.length % 2 == 0
    split_k_array = k**2.to_s.split(//)
    half_k_array_length = split_k_array.length / 2
    i = half_k_array_length
    x1 = 0

    while i > 0
      x1 = x1 + (10**i * split_k_array[i-1])
      i = i - 1
    end

    x2 = 0
    i = split_k_array.length

    while i > half_k_array_length
      x2 = x2 + (10**(i-half_k_array_length))
      i = i - 1
    end

    if k == x1 + x2
      return true
    else
      return false
    end

  else

    puts "Let's figure out what wrong with the other code first :("
    return "Meh"

  end

end

if kaprekar(500500)
  puts "500500 is True :)"
else
  puts "500500 is False :("
end

if kaprekar(9)
  puts "9 is True :)"
else
  puts "9 is False :("
end

если kaprekar(22) ставит "22 верно", иначе ставит "22 неверно" end

Этот код не возвращает никаких ошибок, но пока квадрат k представляет собой четное число цифр, независимо от того, является ли предоставленное число числом Капрекара или нет, метод возвращает значение True. На самом деле, даже если я изменю тестовую часть на:

if x1 + x2 = k
  return false
else
  return false
end

... Я все еще получаю True вернулся ко мне! Как это возможно?

Любая помощь будет оценена по достоинству!

РЕДАКТИРОВАТЬ 1: я исправил назначения правды, чтобы читать "==" вместо "=", и я изменил показатели степени "^" на "**". Тем не менее, мне по-прежнему возвращается «Истина» в обоих случаях, описанных выше. :(

РЕДАКТИРОВАТЬ 2: Кажется, я пропустил 2 "^"! Починил это!

РЕДАКТИРОВАТЬ 3: добавлен код для проверки метода Kaprekar при каждом запуске кода. Исправлена ​​ошибка в строке (Кажется, я пытался разделить длину строки, а не саму строку. Боже!). В любом случае теперь я получаю сообщение об ошибке: "kaprekarTest.rb:37: неопределенный метод `kaprekar' для main:Object (NoMethodError)" Теперь я только что определил метод kaprekar. почему я должен получить сообщение о том, что такого метода нет?


person Michael Nail    schedule 14.10.2013    source источник
comment
Нет, вы еще не исправили оператор ^. Например, строка 2.   -  person vgoff    schedule 15.10.2013
comment
Извини за это! Я исправил те, что внизу, но пропустил те, что вверху. Спасибо, что нашли время. Я очень ценю это!   -  person Michael Nail    schedule 15.10.2013
comment
Теперь вы должны позаботиться обо всех других ошибках. Например: NoMethodError неопределенный метод `разделить' для 1:Fixnum Из строки 3.   -  person vgoff    schedule 15.10.2013
comment
Я исправил эту ошибку. Теперь я получаю новую ошибку (см. редактирование 3)   -  person Michael Nail    schedule 15.10.2013
comment
Прочтите свое сообщение об ошибке. Очевидно, у вас есть код, в котором вы вызываете метод с именем kaprekar, но у вас нет метода с таким именем. То, что я вижу, это метод под названием kaprekar?, а это совсем другое животное. Вам нужно написать свой код, пока у вас не будет чего-то, что вы в основном будете рады показать. До сих пор все, что мы обсуждали, не имело ничего общего с вашими числовыми тестами, а имело отношение к Ruby. Также исправьте свой блок кода, у вас есть строка прямо под выделением, которое, я думаю, вам действительно нужно в этом блоке кода.   -  person vgoff    schedule 15.10.2013
comment
Пробовал как со знаком вопроса, так и без. Я действительно хотел бы быть доволен кодом. Я думаю, что то, как я справился с этим, концептуально говоря, довольно умно. Я просто не понимаю, почему он зависает. Кроме того, я получил только правильный компилятор Ruby, который возвращает сообщения об ошибках за час до моего последнего сообщения. ^_^; В любом случае, большое спасибо за ваше время! Я уверен, что так или иначе доберусь до сути   -  person Michael Nail    schedule 15.10.2013
comment
Ни я, ни кто-либо другой, скорее всего, не попытаемся ответить на этот вопрос до тех пор, пока не будут устранены все очевидные ошибки времени выполнения, такие как вызов метода, которого просто не существует, попытка разделить числа и попытка умножить число на строку. После того, как они будут исправлены, я думаю, мы сможем атаковать логические ошибки.   -  person vgoff    schedule 20.10.2013


Ответы (5)


лучшее и простое решение, чтобы найти номер kaprekar:

def kaprekar?(k)
  ks = k**2
  lenf = (ks.to_s.length)-1
  lenh = (ks.to_s.length / 2) - 1
  a = ks.to_s[0..lenh].to_i
  b = ks.to_s[lenh+1..lenf].to_i
  k == (a+b)
end
person Praveen_Shukla    schedule 11.07.2015

^ не работает в Ruby. ** является.

> 3^2
=> 1
> 3**2
=> 9
person Philip Hallstrom    schedule 14.10.2013
comment
Спасибо за помощь. Дурак я. Ой! Я исправлю это и дам вам знать, если это сработает. :) - person Michael Nail; 15.10.2013
comment
Я применил и ваши исправления, и исправления vgoff, но все равно получаю те же результаты. Вся правда всегда. :С - person Michael Nail; 15.10.2013
comment
Выложил обновленный код. Думаю, я пропустил два экземпляра ^ раньше. Извини за это. :| Спасибо, что заметили! К сожалению, исправление оставшихся кареток не исправило мою возвращаемую истину, какой бы ни была проблема. Большое спасибо, что нашли время! - person Michael Nail; 15.10.2013

if x1 + x2 = k

Это оператор присваивания, а не условный оператор, и поэтому он всегда будет «истинным».

И, как заявил Филип, «экспоненциальный оператор» - это **, а не ^.

Обновление: вы вызываете (как я упоминал ранее) метод, который не существует, когда вы вызываете if kaprekar(500500), потому что вы определили метод keprekar?.

В вашем методе вам, вероятно, потребуется заключить k**2 в круглые скобки, чтобы вызов .to_s действовал не только на число 2.

Надеюсь, что после этих исправлений вы исправите оставшуюся часть возникающих ошибок, так что, по крайней мере, мы сможем добраться до того момента, когда мы сможем «сначала выяснить, что не так с другим кодом».

Этот код даст вам ответы. Не проверено на фактическую правильность этих чисел, но, по крайней мере, не возникает ошибок синтаксиса или времени выполнения.

def kaprekar(k)

  if k**2.to_s.length % 2 == 0
    split_k_array = (k**2).to_s.split(//)
    half_k_array_length = split_k_array.length / 2
    i = half_k_array_length
    x1 = 0

    while i > 0
      x1 = x1 + ((10**i) * split_k_array[i-1].to_f)
      i = i - 1
    end

    x2 = 0
    i = split_k_array.length

    while i > half_k_array_length
      x2 = x2 + (10**(i-half_k_array_length))
      i = i - 1
    end

    if k == x1 + x2
      return true
    else
      return false
    end

  else

  end

end

if kaprekar(500500)
  puts "500500 is True :)"
else
  puts "500500 is False :("
end

if kaprekar(9)
  puts "9 is True :)"
else
  puts "9 is False :("
end
person vgoff    schedule 14.10.2013
comment
Хорошо. Я собираюсь исправить свой код, используя ваш совет. Я вернусь! - person Michael Nail; 15.10.2013
comment
Хорошо, я исправил то, что вы оба упомянули, но я все еще получаю результаты, описанные в исходном вопросе. :( Есть ли какие-либо другие причины, по которым мое утверждение if/else не будет влиять на то, получу ли я правдивый ответ или нет? - person Michael Nail; 15.10.2013

КАПРЕКАР

def convert_array(number)
  arr = []
  div = 10**(number.to_s.length - 1)

  while div >= 10 do
    arr << (number/div)
    number = (number%div)
    div = (div / 10)
  end

  arr << number
  arr
end

def kaprekar?(number)
  c = convert_array(number**2)
  i = 0
  flag = false

  while i < c.length do
    if number == (c.first(i).join().to_i + c.last(c.length - i).join().to_i)
      flag = true
      break
    end

    i = i+1
  end

  flag
end

Попробуй это.

person Santanu    schedule 16.07.2015

Если вы хотите сделать это более кратким:

def kaprekar?(k)
  k_squared = (k*k).to_s
  idx = k_squared.length / 2
  return k_squared[0..idx-1].to_i + k_squared[idx..-1].to_i == k
end

В качестве примечания: хотелось бы узнать, придумает ли кто-нибудь более быструю реализацию ruby?

require 'benchmark'
puts Benchmark.measure{ (1..10000000).select{|k| kaprekar?(k)} }

урожаи

ruby kaprekar.rb
11.240000   0.010000  11.250000 ( 11.249131)

на моей машине.

Изменить: опубликована более короткая версия решения

person tobias.henn    schedule 22.12.2013