我预感到我今天要和面试官就一道简单的算法题进行讨(si)论(bi)了,先上 v 站和你们讨论一下,寻找一下底气。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
jadetang
V2EX    求职

我预感到我今天要和面试官就一道简单的算法题进行讨(si)论(bi)了,先上 v 站和你们讨论一下,寻找一下底气。

  •  
  •   jadetang 2015-05-15 08:14:37 +08:00 10033 次点击
    这是一个创建于 3809 天前的主题,其中的信息可能已经有所发展或是发生改变。
    今天面试,有一道面试题是这样的:
    “首歌曲都是一个评分,现在有2000首歌曲,要求实现一个随机播放器,每首歌曲播放的概率应该正比于它的评分,例如评分9.1的歌曲,和评分7.9的歌曲,播放的次数应该是91:79”
    当时给出了一个比较复杂,但是有缺陷的接,之后面试官给出了答案,当时也没有细想,回家路上想出了更好的解法,就写在了我的博客上,顺便让面试官看一下(面试通过不通过无所谓,程序的孰优孰劣必须要分个清楚)。http://www.cnblogs.com/javanerd/p/4504482.html
    总的来说我的解法:

    拿空间换时间,评分9.1的歌曲,复制91份,评分7.9的歌曲复制79份,放到一个数组中,随机从里面拿。优点就是浅显易懂,实现起来也容易(当时是面试哦,手写代码,人都会紧张的吧)。缺点是空间复杂度不好,如果全是9.9分的歌曲,那么就悲剧了。但是每次随机选取的歌曲的时间还是O(1),所以随着听得歌曲越多,效率其实越高。


    面试官的解法:
    将评分和歌曲序号维护成一个区间和歌曲序号的map,然后生成一个随机数,落在哪个区间里面,就是哪首歌。那么问题来了?如果是一个区间做key的map,我只有一个随机数,如何正确的拿到value?是不是应该说的是线段树?如果用线段树,是不是要先排序,才能找到最大的评分的歌曲。

    面试官的小弟已经回复我了,估计一会面试官也会看到,我已经做好讨(si)论(bi)的准备了,求V友给点信心。

    另外,求一个珠三角地区后端的工作,能用scala就最好不过了,java也行。
    第 1 条附言    2015-05-15 09:46:19 +08:00
    谢谢V友热情的打脸,对这个题目我更加理解了。
    根据http://www.electricmonk.nl/log/2009/12/23/weighted-random-distribution/
    1 我的算法,叫做expanded,
    优点:快速,简单
    缺点:占有内存大。

    2.面试官的算法,是in-place,占用空间都小。
    其中in-place的算法又分为排序和不排序的,
    如果不排序,每次选择都很慢,优点是更新快。

    如果排序,每次选择速度优于不排序的in-place算法,缺点是需要预先排序,更新也很慢
    67 条回复    2015-05-18 14:48:34 +08:00
    laoyuan
        1
    laoyuan  
       2015-05-15 08:23:16 +08:00
    虾米么,虾米收藏的音乐别人最多只能看到2000。
    你的解法和面试官的不是一个意思么。。。
    zmj1316
        2
    zmj1316  
       2015-05-15 08:25:49 +08:00
    觉得面试官的解法更加优雅一点
    sNullp
        3
    sNullp  
       2015-05-15 08:31:04 +08:00 via iPhone
    如果评分不是7.9而是7.96你怎么办。
    jadetang
        4
    jadetang  
    OP
       2015-05-15 08:31:12 +08:00
    @laoyuan
    不是虾米

    @zmj1316
    关键是我想不明白,如何从区间里面拿到对应的key,例如有三首歌的评分[1,2,3],那么有三个区间[0-1,1-3,3-6],现在给出一个随机数3.6,有什么数据结构能够判断出,3.6是在第三个区间里面?
    也许我真的想错了,所以要先到V站上来找答案啊。
    crisrock
        5
    crisrock  
       2015-05-15 08:32:32 +08:00
    1首歌评1分,其余评分为0,岂不是一直播1首歌?这还是随机吗?
    jadetang
        6
    jadetang  
    OP
       2015-05-15 08:33:02 +08:00
    @sNullp
    我只能说,基于题目给出的条件,这样的算法是最合适的,每个算法都是优缺点吧。如果是评分是后两位小数,那我的算法空间复杂度还是o(n),不过已经高一个数量级了。
    jadetang
        7
    jadetang  
    OP
       2015-05-15 08:34:02 +08:00
    @crisrock
    看题目的字面要求,如果是评分是1和0的话,那么播放的概率比应该是1:0。
    osto
        8
    osto  
       2015-05-15 08:35:51 +08:00
    lz你这样思路是非常清晰的. 面试官给出的solution其实是你的改进版

    本质都是索引集合A映射到歌曲集合B.

    你采用了粗暴的拷贝歌曲实例到集合A.
    其实可以A可以只需要存歌曲号什么的, 这可以大大算减空间,映射函数也简单.
    面试官的算法把A弄成自然数集合, 但是映射函数会稍微复杂. 但时空效率确实是最高的, 考虑到才2000首歌, 定义域A的范围不会超过2000*100, A用int表示也绰绰有余了.
    raptium
        9
    raptium  
       2015-05-15 08:36:48 +08:00 via iPhone
    @jadetang 未必要 O(1) 啊,这种规模二分也找的过来
    差不了几毫秒
    jadetang
        10
    jadetang  
    OP
       2015-05-15 08:41:46 +08:00
    @osto
    你说到点子上了,我的scala解,返回的就是歌曲的下标。而且每次选择都是o(1)的时间。

    我主要想不出面试官的的映射函数是怎么样的,这个函数能否达到o(1)的时间。或者根本没有这样的映射?



    class RandomSong(val rate: Array[Double]) {
    val rateWithIndex = rate.map(x => (x * 10).toInt).zipWithIndex

    val sOngPool= rateWithIndex.flatMap { case (rate, index) => Array(index).padTo(rate, index)}

    def pickSong:Int = songPool(Random.nextInt(songPool.size))

    }
    yingluck
        11
    yingluck  
       2015-05-15 08:43:41 +08:00
    ‘’‘评分9.1的歌曲,复制91份‘’‘

    这里是歌名或者歌曲编号复制91份吧
    jadetang
        12
    jadetang  
    OP
       2015-05-15 08:44:17 +08:00
    @raptium
    二分查找的话,是离散的查找吧。比如歌曲的评分是 [1,2,3,]如果是你生成的随机数,只有1,2,3这个三个取值,那么自然hashMap什么的是最高效的。问题是,需要把离散的评分,变成连续的区间段,这个时候能用2分查找?也许线段树能做到?等高人解答。
    jadetang
        13
    jadetang  
    OP
       2015-05-15 08:45:23 +08:00
    @yingluck
    我给的出的解是一个数组,下标是歌曲的编号,数组值是歌曲的评分,每次返回下标。
    raptium
        14
    raptium  
       2015-05-15 08:55:01 +08:00 via iPhone
    不知道我理解错了没
    Guava 里 有个 RangeMap 类,就是二分查找实现的
    laoyuan
        15
    laoyuan  
       2015-05-15 09:01:40 +08:00
    歌曲的评分是 [1,2,3,],生成的是[1,2,3,4,5,6],同时记录[1] => 1、[2, 3] => 2、[4,5,6] => 3
    所以我说和LZ的解法是一个意思
    sciooga
        16
    sciooga  
       2015-05-15 09:01:52 +08:00 via Android
    看看这样如何?
    评分假设只有1位小数,v = random 一位小数,抽一首歌,评分比v大则播放,比v小则跳过抽下一首?
    laoyuan
        17
    laoyuan  
       2015-05-15 09:04:03 +08:00
    自然数区间构成的序列,相当于一个连续数组,也是分多的多,分少的少,无非就是不用那么多元素了,光记个开头的数就行了其实
    osto
        18
    osto  
       2015-05-15 09:10:31 +08:00
    @jadetang
    用 if else 硬编码写在代码里可以接近O(1)时间, 哈哈

    猜测实际项目是在数据库的歌曲表存了范围, 然后用查询语句取出歌曲.这时候时间肯定不止O(1)
    这种情况的话lz的时间是要更优一点的.

    假设存数组的歌曲引用只有8个字节(64bit机器), 那么需要的最大内存是 2000*8*100 <= 1.6 M.
    在题目给出的设定是完全可以接受的.

    开下脑洞, 在正常实际情况,这是一个用户的情况, 要支持大量用户的话可能内存就会不够了. 而感觉实际支持大规模用户的使用情况中, 时间也许没那么宝贵, 反而内存空间会.
    Andiry div class="fr">     20
    Andiry  
       2015-05-15 09:19:56 +08:00
    @jadetang 不就是个数组吗,有什么高级的
    a[0] = 0
    a[1] = 91 // point(0) = 91
    a[2] = 160 // point(1) = 79

    然后二分查找
    jadetang
        21
    jadetang  
    OP
       2015-05-15 09:20:53 +08:00
    @Septembers
    目前看来,你这个答案最靠谱的,果然V站牛人多,谢谢了。
    WDsUO7HnS2Na1DFC
        22
    WDsUO7HnS2Na1DFC  
       2015-05-15 09:21:35 +08:00
    我的理解
    [1,2,3,4,5,6] ---> [1,3,6,10,15,21]
    1-21随机取一个ra
    取min(a[n] >= ra)
    stiekel
        23
    stiekel  
       2015-05-15 09:22:00 +08:00
    这是一个典型的权重算法。比较经典和方便的方法是:
    1、遍历,求出所有项的总权重
    2、遍历,给每一项的权重,加一个0到总权重之间的随机数,注意,每项加的都是随机数,大小是不一样的。得出新权重
    3、从所有项中,找出新权重最大的那一项。
    难道我也要写一篇吗?
    stiekel
        24
    stiekel  
       2015-05-15 09:22:57 +08:00
    这个算法,只需要遍历两次。
    jadetang
        25
    jadetang  
    OP
       2015-05-15 09:23:31 +08:00   1
    @Andiry
    啊,我想通了,确实这样能达到Log(n)的速度。
    Andiry
        26
    Andiry  
       2015-05-15 09:24:24 +08:00
    算错了,a[2] = 170
    lijia18
        27
    lijia18  
       2015-05-15 09:38:57 +08:00
    /div>
    这种问题还值得搞个算法啊
    至少要把加like的时间当参数传进来才是好一点的算法啊
    很多人在某个时间段喜欢听某种音乐啊
    越新发布的音乐在收藏里随机到的几率越高啊
    把这些元素都考虑进去再做算法吧
    其他啥好友相似口味这种忽悠的我就不说了
    ffffwh
        28
    ffffwh  
       2015-05-15 09:39:05 +08:00
    @crisrock
    这种常见做法是把0变成0.1之类的
    wshcdr
        29
    wshcdr  
       2015-05-15 09:43:39 +08:00
    你的解法没有什么扩展性
    hualuogeng
        30
    hualuogeng  
       2015-05-15 10:00:19 +08:00
    楼主使用的是整数域, 然后用数组做了一个全map,其它的和面试官的没有什么本质区别。用空间换时间,查询的效率应该最高的。
    但是在评分改变时会有一些额外的开销,比如评分减少了,那么需要重新构建数组。而且在sNullp所说的评分值进一步细化情况下,其空间开销是数量级增长的。

    而面试官的方法使用的是实数域,带来的优势是在评分细化时,其时空开销是不变的,对评分改变的额外开销也比较少。当然,只要不使用全map方式,从随机值到区间的查找肯定不是O(1),楼主的查询效率肯定要更好。

    就本题的限定条件而言,我觉得楼主的算法更优。
    但是如果是实际的开发需求,我会更倾向于面试官的做法,因为1. 有更好的扩展性; 2. 修改的影响小;3. 在2000首这样的数量级上,即使遍历,查询效率也应该够用。
    kifile
        31
    kifile  
       2015-05-15 10:06:07 +08:00
    感觉两个解法一样的啊,只不过你是属于在一个池子里复制多个相同对象,而面试官则是把你那些对象的数字给他抽离了,使用开区间来处理,其实思想都是同一个,只不过他的更省空间一点。
    jadetang
        32
    jadetang  
    OP
       2015-05-15 10:09:13 +08:00
    @hualuogeng
    评分减少了,只需要扫一遍数组,把对应的元素个数给删除出去就行。如果评分增多了,就加元素。

    每个算法都有优缺点,只是看特殊的场景下选择最合适的。

    受教了。
    binux
        33
    binux  
       2015-05-15 10:14:03 +08:00
    面试官的解法明显是 Pre-calculated

    我经常喜欢问的一个类似的题目是,怎样从不定多带权数列中,随机选取 n 个,只遍历一次。
    zjuster
        34
    zjuster  
       2015-05-15 10:23:27 +08:00
    @jadetang 这样把1和0粗暴对待太书面化了。实际上的算法应考虑边界值。比如新加入的歌曲,还没来得及评分,那么就是0。其他都有{1,0.1,0.9,0.7...}的评分,那么0就相当于被无视了。
    jadetang
        35
    jadetang  
    OP
       2015-05-15 10:25:23 +08:00
    @zjuster 面试题毕竟是面试题,不是实际开发啊,如果实际开发的话,很多条件要考虑的,比如,能不能更新评分,能不能新加歌曲,评分精确到小数点以后几位,播放的概率之比允许的偏差等等。
    hualuogeng
        36
    hualuogeng  
       2015-05-15 10:32:07 +08:00
    @jadetang 对于连续存储的数组来说,增删的代价都不小。就算是scala的变长数组,在非尾端删除都会带来其后数组元素的移动。
    xua131988
        37
    xua131988  
       2015-05-15 10:43:06 +08:00
    scala大爱。。
    Septembers
        38
    Septembers  
       2015-05-15 10:45:03 +08:00
    @jadetang
    对于音乐应用这些处理都可以压到后台预处理
    但是考虑到 嵌入式设备 的特殊性,算法的各方面复杂度应该压到最低(电池啊 电池啊 电池啊
    jadetang
        39
    jadetang  
    OP
       2015-05-15 11:01:11 +08:00
    @xua131988 安利一下我写的一个scala sql的实现,可以在内存中对于Map执行sql语句 https://github.com/jadetang/scala_sql
    Septembers
        40
    Septembers  
       2015-05-15 11:05:12 +08:00
    @jadetang scala看起来做DSL似乎很简单
    jadetang
        41
    jadetang  
    OP
       2015-05-15 11:09:49 +08:00
    @Septembers 因为内置了实现parser的包,实现简单的DSL很方便。
    akakcolin
        42
    akakcolin  
       2015-05-15 12:47:45 +08:00
    @sciooga 修改下:比v小则按照一定概率判断是否跳过抽下一首?我怎么看到了monte carlo的影子 :)
    SoloCompany
        43
    SoloCompany  
       2015-05-15 13:04:02 +08:00 via Android
    不就是一个典型的加权平均发布问题么,你的复制(即使是指针)想法出发点就是错的,面试官的区间想法(我没说算法)是对的,具体怎么实现,可以自己把握,最简单易懂的,就是总分乘以0到1的随机因子,然后通过区间累加判断(当然这个累加是可以算法优化的,但通常情况下可以忽略)
    XadillaX
        44
    XadillaX  
       2015-05-15 13:09:51 +08:00
    关于区间的做法很平常的,比如一个随机起名字的包。

    https://github.com/XadillaX/chinese-random-name/blob/master/lib/name.js#L40

    金木、金金、金土等等不同的组合方式有不同的概率(当然这个概率是瞎掰的),就是用区间来判定的。
    sciooga
        45
    sciooga  
       2015-05-15 13:13:09 +08:00
    @akakcolin 哈,难道我的数学水平不知不觉又上升了一个水平吗?
    jadetang
        46
    jadetang  
    OP
       2015-05-15 13:17:30 +08:00
    @SoloCompany 错误肯定是谈不上,只不过这个解逼格没有那么高而已了。只不过面试官期望的不是这个解法而已了。
    jadetang
        47
    jadetang  
    OP
       2015-05-15 13:24:35 +08:00
    @binux
    我看了http://www.electricmonk.nl/log/2009/12/23/weighted-random-distribution/
    里面说的pre-caculate,本质上是排序以后,通过2分查找来确定随机数落在哪个区间的。
    不过面试官给的答案,没有很详细,我自己一开始也没有想到可以用2分查找来定位。
    binux
        48
    binux  
       2015-05-15 13:30:07 +08:00
    @jadetang 做区间不需要排序,而且我觉得这个方法是应该被想到的。。
    jadetang
        49
    jadetang  
    OP
       2015-05-15 13:33:54 +08:00
    @binux 求伪代码,另外,2000首歌,评分0.1-9.9,会有评分重复的。
    SoloCompany
        50
    SoloCompany  
       2015-05-15 13:39:37 +08:00 via Android
    @jadetang 你把浮点问题整数化这还不叫错误? 如果是的话,为何还要在计算机系统上设计浮点数表示?再者,用空间换效率是很常见的,典型的完全平面化bitset数据结构就是其中之一,但在你这个需要解决的问题上下文中显然不是那么合适,hash和list都能实现o0查找效率,你的线性设计显然是有过度优化的嫌疑
    SoloCompany
        51
    SoloCompany  
       2015-05-15 13:43:52 +08:00 via Android
    累加算法 on
    加一个中间累加结果的排序表,ologn
    hash算法好像不存在,没戏想
    平面化,也是o1
    binux
        52
    binux  
       2015-05-15 13:44:54 +08:00
    WeeH9T
        53
    WeeH9T  
       2015-05-15 14:01:20 +08:00
    可参照游戏中常见的宝箱系统

    假设设基础权重都为 10,附加权重为评分 , 物品总权重 = 10 + star * 10
    权重和 = 所有物品总权重相加

    random(1, 权重和) <= 当前物品总权重 + 当前权重累计 break,以上没考虑排序
    jadetang
        54
    jadetang  
    OP
       2015-05-15 14:04:19 +08:00
    @hambut 这种算法,对于有重复权重的情况也成立吗
    WeeH9T
        55
    WeeH9T  
       2015-05-15 14:29:32 +08:00
    @jadetang 成立,不过最好还是打乱一下顺序,最好
    imn1
        56
    imn1  
       2015-05-15 14:42:05 +08:00
    sorry,算法比较弱,没看懂原地(in-place)算法

    但我想你是否把问题想复杂了?这个其实很简单
    生成一个随机数 [0.1, 10.0],如果是5.5,就只能在 [5.5, 10.0] 内再随机选歌;
    如果是3.1,就 [3.1, 10.0] 内选,低于3.1的歌就不会成为候选
    这样高分的歌曲被选中机会,概率必然与分数成正比,这问题不就是问概率么?
    “随机”就应视为机会均等,不影响概率,所以,按正比(概率)生成候选区间就是答案

    其实就是简单“置信区间”的概念
    https://zh.wikipedia.org/zh/%E7%BD%AE%E4%BF%A1%E5%8C%BA%E9%97%B4
    以评分作为置信度,分数越高,置信区间范围越小,可选的歌越少,选中概率越大

    个人觉得面试不会问太难的算法问题,除非岗位就是专门做优化的
    那些对一般岗位考很深奥算法的公司都不知道是怎么想的,期望全公司都是华罗庚?
    whahuzhihao
        57
    whahuzhihao  
       2015-05-15 15:37:25 +08:00
    第一眼看到题目,就想到了“轮盘赌”算法。
    原理跟面试官给的差不多,但是解决方式更简洁。也就是@binux提到的那篇文章里的in-place(unsorted)。
    Mutoo
        58
    Mutoo  
       2015-05-16 00:07:37 +08:00
    同上,正是遗传算法里的「轮盘赌」按概率择优录取的简单应用。
    whatisnew
        59
    whatisnew  
       2015-05-16 00:23:29 +08:00
    我也曾经和楼主一样,我被 pass 了,哈哈哈 t/191444
    gavin2zhang
        60
    gavin2zhang  
       2015-05-16 01:39:47 +08:00 via iPhone   1
    我就是那面试官的「小弟」:P
    LZ对面试官的解答有一处不太明白,我已经在你的博客下留言了。这其实就是一道很平常的算法题,我昨天给你发了个Javascript的实现,如果你认真看应该能想明白。
    楼上有些同学不太理解这道算法题的实际意义,其实我没参与出题的过程,倒是在上家公司遇到了同样的场景,要根据用户对节目的喜好程度随机挑选节目,喜好程度越高,选到的概率越大。所以这道题目对数据工程师来说应该是恰当的。
    两种算法都是work的,但正如我之前留言的,如果评分不是精确到小数点后一位,而是五位六位,你的方法会遇到麻烦,或者说不够优雅。你的算法是暴力的,而面试官的反而是一种「合理」的思考方向。
    再说一句题外话,LZ其实不必太介怀,面试的结果有时可能在对错之外,别人是不是认识到你的潜力反而更关键。天大地大更要心眼大,希望LZ能收获满意的offer啦。:)
    remenberl
        61
    remenberl  
       2015-05-16 03:44:28 +08:00
    jadetang
        62
    jadetang  
    OP
       2015-05-16 07:34:09 +08:00
    @gavin2zhang 我只是对于面试官的解答没有很清楚,所以发个帖子太讨论一下吧。心眼问题谈不上吧。种算法的优劣,http://www.electricmonk.nl/log/2009/12/23/weighted-random-distribution/ 这里面说的很清楚了,根据不同的场景选择最合适的,才是最好的。我昨天吃饭的时候还和朋友讨论,说这样的面试题才好的,能把简单的算法题目变化成一个实际应用的场景,比起直接出LEETCODE上的那种题目,要高明一些。所以,我没用黑你们公司的意思啊,心眼问题实在谈不上。
    starqoq
        63
    starqoq  
       2015-05-17 19:25:33 +08:00
    你好,不需要排序的。直接算出得分数组的前缀和,然后随机一个数字,二分查找前缀和数组就可以了。
    复杂度预处理 O(N)
    取一个数是 O(ln(n))
    starqoq
        64
    starqoq  
       2015-05-17 19:27:08 +08:00
    对了要特殊处理一下评分为0的歌曲。
    bugcoder
        65
    bugcoder  
       2015-05-18 01:54:16 +08:00
    取所有的评分,均一化,作为狄利克雷分布的参数,然后每次选歌就是一次狄利克雷分布的采样。
    mengzhuo
        66
    mengzhuo  
       2015-05-18 12:33:55 +08:00
    轮盘赌啊
    才2000,Log(n)没有问题
    iannil
        67
    iannil  
       2015-05-18 14:48:34 +08:00
    我是来赞楼主头像的,太萌了!
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2634 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 14:42 PVG 22:42 LAX 07:42 JFK 10:42
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86