如何找到指令数最少的模式数字?

时间:2013-02-08 18:06:53

标签: assembly mips

来自用户的输入用于确定数字(最多20位)是否是回文,但我还需要随后找到模式数字。 如果模式数字被绑定,则应打印具有最大值的数字。

我可以使用基本的分支,加载和运算符,例如除法,乘法和加法。

目前我的数字回文方法只是在找到输入字符串的长度后逐个字符地进行比较。

更新: 使用计数器阵列的想法创建了一个解决方案。我计算了在计数循环中找到字符串长度的每个数字的出现次数。 在find_mode循环中,我稍后遍历计数器数组并比较每个出现次数。 可能不是最佳(最少指令计数),但它的工作原理。 谢谢gusbro的指导!

    .data
buf1:   .space  21     # receive original input in this buffer
counters: .byte 0,0,0,0,0,0,0,0,0,0 # counters for digits 0-9 for number of occurrences

# the following are constant strings that you can use for your prompts and messages
msgin:  .asciiz "Enter up to 20 digits without spaces: "
msg1:   .asciiz "\nYour string: "
msg2:   .asciiz " IS a palindrome\n"
msg3:   .asciiz " IS NOT a palindrome\n"
msg4:   .asciiz "\nThe mode digit is: "

# print this string for a newline character
nline:  .asciiz "\n"

    .text
main:
li $v0, 4 
la $a0, msgin
syscall # print msgin
li $v0, 8
la $a0, buf1
la $a1, 20
syscall # read string
li $v0, 4
la $a0, msg1
syscall # print msg1
li $v0, 4
la $a0, buf1
syscall # print user input

la $a1,buf1
add $t3, $0, $0 # counter of input length

count:
lb $t1,($a1)
beq $t1, 10, initialize # branches if it reaches the LF character

#this part is for the mode digit counters
subu $t1, $t1, '0'
lb $t2, counters($t1)
addi $t2, $t2, 1
sb $t2, counters($t1) # update counters(i)

addi $t3, $t3, 1 # increase counter
addi $a1,$a1,1 # traverse the string
b count

initialize:
la $a1, buf1 # sets up pointer going forwards
la $a2, buf1 # sets up pointer going backwards

div $t4, $t3, 2 # get the amount needed to traverse backwards, so that odd number palindromes work too

addi $t3, $t3, -1 # last digit will be at (input length - 1)
add $a2, $a2, $t3 # move the second pointer to the last digit

check:
beq $t4, $0, isPalindrome # if the traverse counter = 0, nothing left to traverse
lb $t1, ($a1) # starting digit
lb $t2, ($a2) # ending digit
bne $t1, $t2, isNotPalindrome
addi $t4, $t4, -1 # reduce amount to traverse by 1
addi $a1,$a1,1 # move pointer forwards
addi $a2,$a2,-1 # move pointer backwards   
b check

isPalindrome:
li $v0, 4
la $a0, msg2
syscall # print is palindrome
b mode

isNotPalindrome:
li $v0, 4
la $a0, msg3
syscall # print not palindrome
b mode

mode:   
addi $t7, $0, 0 # counter for number of occurrences
add $t6, $0, $0 # counter to know if done iterating
addi $t5, $0, 0 # the mode digit
la $a1, counters

find_mode:
beq $t6, 10, print # stops iterating through
lb $t1, ($a1)
bge $t1, $t7, store_mode # number of occurences are higher, go store the new mode digit
addi $t6, $t6, 1 # moves counter forward
addi $a1, $a1, 1 # moves pointer forward
b find_mode

store_mode:
add $t7, $t1, $0 # stores the highest number of occurrences
add $t5, $t6, $0 #stores the actual number
addi $t6, $t6, 1 #moves counter forward
addi $a1, $a1, 1 # moves pointer forward
b find_mode

print:
li $v0, 4
la $a0, msg4
syscall
li $v0, 1
move $a0, $t5 # prints mode digit
syscall

exit:
li $v0,10
syscall

1 个答案:

答案 0 :(得分:1)

您可能有一个包含10个计数器的数组(每个数字一个)。 当您计算字符串是否为回文时,您可以更新这些计数器: 首先在数据部分声明数组:

counters: .byte 0,0,0,0,0,0,0,0,0,0   # counters for 10 digits

然后在检查字符串是否为回文时更新计数器

addi $a2,$a2,-1 #move pointer backwards  --- your code
  subu $t1, $t1, '0'
  lb $t2, counters($t1)
  addi $t2, $t2, 2
  sb $t2, counters($t1) # update counters(i)
b check  # --------your code

如果是回文,你仍然需要考虑字符串是偶数还是奇数(如果不考虑中间数字,则计算中间数字):

# This code should go after you print that the string is palindrome
# Update counter if string was odd
  andi $t3, $t3, 1
  bnez $t3, even
  lb $t1, ($a1)
  subu $t1, $t1, '0'
  lb $t2, counters($t1)
  addi $t2, $t2, 1
  sb $t2, counters($t1) # update counters(i)
even:

现在对计数器进行线性搜索以获得模式:

  addu $a1, $0, 9
  xor $t2, $t2, $t2
find_mode:
  lb $t1, counters($a1)
  ble $t1, $t2, not_mode
  move $t2, $t1
  move $t3, $a1
not_mode:  
  subu $a1, $a1, 1
  bnez $a1, find_mode

并打印结果......

  li $v0, 4
  la $a0, msg4
  syscall
  li $v0, 1
  move $a0, $t3
  syscall