D-29. 常数, 变数, 符号, 数字 && Leetcode : Power_of

资料型态

多数程序语言的学习第一步常为了解资料型态,毕竟分不清楚资料的型态的话,就不可能对资料做出正确处理或判断,以比喻来说,买股票时,明知道电子股会涨,但是却买进保护伞公司的股票,以为保护伞公司是电子科技股,结果是搞生化的!?

Ruby的设计风格

多数文章资料都会直接说一句Ruby里几乎所有东西都为物件,造成这点的原因是,Ruby在设计上已经将资料的特性与方法包装後,组成各种class,所谓的东西都是指class产生的实体。

BasicObject为所有常用类别的顶端(但Class的顶端是Module),再以duck typing设计风格,将资料特性分组好,给予我们想要执行的方法包装好後,再给予一个名字(标签,常数),就成了许多的新class。

物件即为class的实体化,所以物件本身就包含了特性与方法,所以才可以操作物件,因此Ruby内所有东西都为物件

不是所有物件导向设计的程序语言都是如此设计,但Ruby这样设计,且物件导向的很彻底。

wiki--物件导向程序设计
文章尽量导向中文资料,能力许可下还是看英文资料较好。

常见资料类别

Ruby中有个语法,在资料後面加上.class,可以查资料的类别。

2.7.3 :020 > :a1234.class
 => Symbol
2.7.3 :021 > 1234.class
 => Integer
2.7.3 :022 > "1234".class
 => String  #有""或''的就为字串。
2.7.3 :023 > [1, 2, 3, 4].class
 => Array
2.7.3 :024 > (1..4).class
 => Range
2.7.3 :025 > {:a => 1, "b" => 2, c: 3}.class
 => Hash

另外可以用.methods对类别产生的实体查询本身有哪些方法。(方法等於怎麽操作这些资料)

2.7.3 :022 > new_array = Array.new
 => []
2.7.3 :023 > new_array.methods
 => [:to_h, :include?, :&, :*, :+, :-, :at, :fetch, :last, :union, :difference, :intersection, :push, :append, :pop, :shift, :unshift, :each_index, :join, :rotate, :rotate!, :sort!, :sort_by!, :collect!, :map!, :select!, :filter!, :keep_if, :values_at, :delete_at,
 略....]
#太多了
2.7.3 :024 > new_array.methods.size
 => 192
#192种.
2.7.3 :067 > Array.methods.size
 => 114
#补充:Array原生只有114种方法,new出来的有多78种。可以两者相减看看多哪些方法
Array.methods - new_array.methods

较特殊的。

2.7.3 :024 > true.class
 => TrueClass
2.7.3 :025 > false.class
 => FalseClass
2.7.3 :026 > nil.class
 => NilClass  #null或其他语言可能拼法不同。

布林值,Ruby没有这种型别,但是有给予类别,在我个人学习後会比较让自己去记得Ruby只有类别,没有型别。
但是资料的确是都有自己的型态没错。(记忆体储存方式)
nil就是空的,会去记,Ruby为了让你看到空白,所以让你看到nil

2.7.3 :003 > nil.to_s
 => ""
#真的如果有新手路过看到这个还看不懂,请先略过之後都会说明。

当然Ruby中不只这六种类别,这六种为比较常见的Ruby资料类别而已,初学会以这几种出发。除了符号这类别可能比较陌生,还有Hash在Ruby叫杂凑外,其他的资料处理方式都与其他程序大同小异。认识资料类别最大目的为,怎麽处理资料,Ruby虽然为强型别语言,但个类别间有很多方法做转换,甚至有很多同名方法,初学以能越快速掌握越好。而由於网路上大神们的资料已经够详细,我将会直接以解题做分享。


变数、常数

为何需要变数或常数?

Ruby是物件导向程序设计的语言。
无论了不了解OOP,先知道如果需要处理物件,以变数来指向,会比较便利。
变数与常数简单一点来想就是,只是一个标签(名字),拿来指向一个物件,物件於Ruby多指类别的实例,也就是实体,最简单的实体就是基础的资料,指向完成後,变数成为了实体(物件)的名字,我们可以将变数拿来操作,不用重复输入物件(实体)。

怎麽指向?

例如:x = 123
看起来像x这个变数等於123
事实上x这变数指向123
=是个指向方法,不是等於。

例如:

2.7.3 :091 > num = 202120212021
 => 202120212021
2.7.3 :092 > num / 2021
 => 100010001
2.7.3 :093 > num * 2021
 => 408484948494441
2.7.3 :094 > num - 2021
 => 202120210000

以及以後会常看到的

2.7.3 :099 > num = 10
 => 10
2.7.3 :100 > num
 => 10
2.7.3 :101 > num = num - 5
 => 5
2.7.3 :102 > num
 => 5
2.7.3 :103 > num = num * 5
 => 25
2.7.3 :104 > num
 => 25
#赋予运算,下面会稍微提到为何可以如此操作。

变数与常数差异?

变数为开头小写英文的数字加组合,如abca123a1b1aAaa,除了_不要有计算符号於内,如a+ca@ax123^这些都会造成错误。

常数为开头大写英文的数字加组合,其余与变数相同,如AbcA_BC
因此於Ruby,除开头大小写外,使用Ruby者多以常数指向不轻易变动之资料,若要变动则会有警告提示(而已),所以类别与模组强制使用常数来命名。

2.7.3 :005 > num = 1
 => 1
2.7.3 :006 > num = 2
 => 2
2.7.3 :007 > num = 3
 => 3
2.7.3 :008 > Num = 1
 => 1
2.7.3 :009 > Num = 2
(irb):9: warning: already initialized constant Num
(irb):8: warning: previous definition of Num was here
 => 2
#对,就警告而已,我们是大人了,不要做被警告的事就好。

2.7.3 :012 > def Add(num1, num2)
2.7.3 :013 >   num1 + num2
2.7.3 :014 > end
 => :Add   #方法用变数,这是错误示范,强调Ruby的风格较自由,但Ruby使用者不会这麽做。

2.7.3 :015 > class error
2.7.3 :016 >   p "错误"
2.7.3 :017 > end
SyntaxError ((irb):15: class/module name must be CONSTANT)
class error
      ^~~~~  #没有例外
#类别只能用常数。

命名原则

保持可阅读性,宁可越详细越好,也尽量不要有xaxy、这种无意义的魔法编码。
请让一年後的自己还知道自己了写什麽
使用者多以蛇式命名、first_number

保留变数:很多,记会喷错就代表不能用,例如不可能会有nil = 123if = 123

变数种类

会於进入Rails前说明。

请记得变数与常数未指向任何实体前,没有实际上的意义。


符号与字串差别,符号与变数差别?

我们先了解怎麽用。

什麽是符号?
符号指:加上变数。变数前面挂上:就会成为符号。

2.7.3 :019 > :abc
 => :abc
2.7.3 :010 > :acb.class
 => Symbol

#不是:是符号,而是:abc是一个符号。
#不是指+,-,*,%这些已经被包装成方法的运算式,也不是指@, #, $这些。

符号常见於Hash中当做Key指向Value,{:a => 1},或将方法名称标记,等於是一个固定住的物件。

2.7.3 :001 > def some_method
2.7.3 :002 >   p "do something"
2.7.3 :003 > end
 => :some_method
# 运用到Rails上会看到下面类似使用方式。
after_save :some_method
# 在实体存挡後执行一个方法。

#我们可以随意将变数随意拿来使用
2.7.3 :004 > some_method = 123
 => 123
2.7.3 :005 > some_method = 1234
 => 1234
#但符号不能
2.7.3 :006 > :some_method = 123
SyntaxError ((irb):6: syntax error, unexpected '=', expecting end-of-input)
:some_method = 123
             ^
#即使变数一直改指定,刚刚def的方法不会受影响。
2.7.3 :007 > some_method()
"do_something"
 => "do_something"

some_method这串英文只是变数,可以指向任何资料,也可以当方法的名称。
:some_method等於是有个方法(物件)出现了,给他除了变数外,加固给他一个特别的名字。

Hash中,字串也可以当Key。

2.7.3 :025 > {:a => 1, "b" => 2, c: 3}.class
 => Hash
#上面写法错误示范,下篇介绍Hash会说明。

但符号的记忆体位置是固定的,字串不是。

2.7.3 :014 > :some_method.object_id
 => 2041948
2.7.3 :015 > :some_method.object_id
 => 2041948
2.7.3 :016 > "some_method".object_id
 => 180
2.7.3 :017 > "some_method".object_id
 => 200
2.7.3 :018 > "some_method".object_id
 => 220
2.7.3 :019 > "some_method".object_id
#也所以Rails还是常见。
after_save :some_method
#下面也是可以。
after_save "some_method"

整理

符号,字串,变数三者是不同的。
符号,字串为类别的一种,:symbol"string"则已经是实体(物件),变数只是指向物件(实体)的标签。
符号,字串都可以当KEY指向物件,而由於记忆体固定,处理符号会比处理字串稍快,但字串本身具有方法就多,选用上可视状况更改。

回头看到上面的 num = num + 1

符号与字串就不能这样操作,在指向(=)这个方法前面只能是变数。
那 = 这方法是前面先执行还是後面先执行?

2.7.3 :002 > x.class
NameError (undefined local variable or method `x' for main:Object)
#x是变数,不是任何类别

2.7.3 :003 > x = z
NameError (undefined local variable or method `z' for main:Object)
#z是变数,但没指向任何物件。

2.7.3 :004 > x.class
 => NilClass
#但是刚刚的x已经变成一种nil类别的。但还是没有意义喔nil於Ruby就是nil。

2.7.3 :005 > z.class
NameError (undefined local variable or method `z' for main:Object)
#z却没有

我会先回答,= 将前面变数预设成nilcalss,= 後面是运算式(或方法或物件)的回传值。
答非所问!?


数字

2.7.3 :019 > 1.class
 => Integer
2.7.3 :020 > 0101.class
 => Integer  #2进制
2.7.3 :030 > "32".to_i.class #=> 32
 => Integer
2.7.3 :025 > x = 50
 => 50
2.7.3 :026 > x.class
 => Integer #变数指向什麽资料,变数则表示什麽类别。
2.7.3 :027 > arr = [1, 2, 4, 5]
 => [1, 2, 4, 5]
2.7.3 :028 > y = arr.size
 => 4
2.7.3 :029 > y.class
 => Integer
 2.7.3 :031 > (x - y).class
 => Integer #运算式,方法结果为数字,类别则为数字。

处理数字类别时,理所当然的对数学越了解越吃香,但数学不强,至少要认识基本运算符号到底求的是什麽。

2 * 3 #=>6 ,一个*是乘法
2 ** 3 #=>8 ,两个**是次方
10 / 2 #=>5 ,/ 是求商
10 % 2 #=>0 ,% 是求余
#赋予运算 +=, /=, *=等
#判断 ==, !=, <, >等。

数字的兄弟:浮点数

2.7.3 :032 > 1.0.class
 => Float
2.7.3 :033 > 1.0342342343.class
 => Float
2.7.3 :034 > y = 7 / 3
 => 2
2.7.3 :035 > y.class
 => Integer
2.7.3 :036 > y = 7 / 3.0
 => 2.3333333333333335
2.7.3 :037 > y.class
 => Float

初期最重要一点,Integer与Float运算结果为Float。

第一天的Leetcode题:Power of Two & Power of Three & Power of Four

这三题刚好都可以用单纯数学来解,所以一起说了避免我之後偷懒拿来混天数
另外预防针:由於菜鸟,时间空间复杂度我不会去讨论,能解优先。

题目连结Power of Two:https://leetcode.com/problems/power-of-two/
题目连结Power of Three:https://leetcode.com/problems/power-of-three/
题目连结:Power of Four:https://leetcode.com/problems/power-of-four/

三题分别求Input是否为2, 3, 4的次方数。
三题都可以跑回圈

#0次方都是等於1,所以1一定对。
return true if n == 1
#设定自乘次数起始值
power_number = 1 #设1是因为0次方是1
#Input都一定是2或3或4,自己乘自己N次後会变成的数。请记得我们在三题一起解..
while power_number < n
  power_number *= 2 #或3 , 4
end
  power_number == n

整理一下

def is_power_of_?(n) # ? = two, three, four
  return true if n == 1
  power_number = 1 #设1是因为0次方是1

  while power_number < n
    power_number *= ? #?请自行换2,3,4
  end
  power_number == n
end

而数学比较好的人,可能会了解,2或3的(n次方数大的)除以2或3的(n次方数小的),一定没有余数这件事。

2.7.3 :036 > (2**100)%(2**50)
 => 0
2.7.3 :037 > (2**100)%(2**99)
 => 0
2.7.3 :038 > (2**100)%(2**4)
 => 0
2.7.3 :039 > (2**100)%(2**0)
 => 0

所以可以更快的想到另一种解答。

  #2的,为何用2的32次方,因为题目提示有说 n < 2**32
  n <= 0 ? false : (2**32 % n == 0)
  #3的,1162261467是3的19次方,20次方就超过 2**32了
  n > 0 && 1162261467 % n == 0

2用三元运算子写,3用两个判断句合并,写法不同目的相同。
另外,4的确也符合(大的N次方)%(小的N次方)是余零这件事,但是由於4 = 2*2这件事,所以不会直接拿来解,但可以利用

(4**n - 1) % 3 == 0

这个逻辑来解喔。

本日结束,明日会用其他例题说明字串,范围,阵列,杂凑。


整理今天提到。
1.变数与常数差异。
2.符号、变数、字串三者差异。
3.资料基本型态:Integer
4.leetcode:power_of_two..four


<<:  Day01-认识环境

>>:  Day 01:Hello Computer Science!

Day 28 ~ AI从入门到放弃 - 猫狗辨识之三

今天延续之前的主题,我们将使用EfficientNetB0的架构,但不使用预训练权重,参考了Kera...

DAY11-JavaScript(一)

前言: 前面我们介绍了很多html, css, php和mysql相关的内容了!今天我们要继续来介...

EP 2: Format the project design of TopStore App for MVVM framework

Hello, 各位 iT邦帮忙 的粉丝们大家好~~~ 本篇是 Re: 从零开始用 Xamarin 技...

DAY14:Toast显示讯息之简介

今天要来说到显示讯息,从我们使用电脑的过程中,很常会遇到跳出对话框让我们选择是或否或取消,或是当我们...

Day10:今天来谈一下如何使用Parrot Security的nmap扫描NFS资讯

今天我们要示范如何用Parrot Security的nmap来执行NFS Enumeration(列...