ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: lee1892

[Excel 程序开发] [第99期][VBA&函数公式]最少的旋转次数[已总结]

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2013-11-12 18:55 | 显示全部楼层
一个只会函数的人,就解一下函数的题目吧
  1. =MATCH(,MMULT(N(MID(A2&A2&REPT("z",99),ROW($1:$100),100)>MID(A2&A2&REPT("z",99),COLUMN(A:CV),100)),ROW(1:100)^0),)-1
复制代码

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2013-11-13 16:59 | 显示全部楼层
函数的
  1. =MATCH(0,MMULT(-(MID(A2&A2,ROW($1:$99),99)>MID(A2&A2,COLUMN(A:CU),99)&"阿"),ROW($1:$99)),)-1
复制代码

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2013-11-14 10:20 | 显示全部楼层
本帖最后由 delete_007 于 2013-11-26 18:29 编辑

函数。好不容易凑的,可以计算256个字符的字符串。=MIN(MMULT(-(MID(A1&A1,ROW($1:$256),LEN(A1))>MID(A1&A1,COLUMN(1:1),LEN(A1))),-(ROW($2:$257)<LEN(A1)))/1%+ROW($1:$256))-1




VBA  时间不好控制

Function MinRot(ByVal sStr As String) As Long
    Dim t#
    t = Timer
    '……
    Dim x, y, z As String
    MinRot = 0
    x = sStr
    z = sStr
    Dim i As Integer
    For i = 1 To Len(sStr)
    y = Mid(x, 2, Len(x)) & Left(x, 1)
    If y < z Then z = y: MinRot = i
    x = y
    Next
    '……
    t = Timer - t
    Debug.Print "ID: " & "hellohaha"
    Debug.Print "Answer is: " & MinRot
    Debug.Print "Time used: " & Format(t, "0.000s")
End Function
公式稍有瑕疵,修改为适应小于100字符的公式:
=MIN(MMULT(-(MID(A2&A2,ROW($1:$99),LEN(A2))>MID(A2&A2,COLUMN(A:CU),LEN(A2))),-(ROW($1:$99)<LEN(A2)))/1%+ROW($1:$99))-1
118字符。



——delete_007

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2013-11-17 12:02 | 显示全部楼层
  1. Public Function MinRot(ByVal sStr As String) As Long
  2.     Dim t#
  3.     t = Timer
  4.    
  5.     Dim minIndex As Long
  6.     Dim minString As String
  7.     Dim length As Long
  8.    
  9.     length = Len(sStr)
  10.     minIndex = 0
  11.     minString = sStr
  12.    
  13.     For i = 1 To length - 1
  14.         currString = Right(sStr, length - i) & Left(sStr, i)
  15.         If currString < minString Then
  16.             minString = currString
  17.             minIndex = i
  18.         End If
  19.     Next i

  20.     MinRot = minIndex
  21.    
  22.     t = Timer - t
  23.     Debug.Print "ID: " & "formatd"
  24.     Debug.Print "Answer is: " & MinRot
  25.     Debug.Print "Time used: " & Format(t, "0.000s")
  26. End Function
复制代码

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2013-11-19 13:45 | 显示全部楼层
本帖最后由 qy1219no2 于 2013-11-19 13:46 编辑

比赛日期:2013-10-26至2013-11-25,在此之前请勿答题!
在10月26日之前,还是在11月25日前?
最小字符串?这个概念好陌生?从楼主举的列来看,是不是就是轮回到原始字串前的那个字串?如果不是,楼主是否应该多举几个列来说明一下。

点评

在竞赛期间才能答题。开赛之前不能答题,竞赛结束后答题无效。  发表于 2013-11-27 16:10

TA的精华主题

TA的得分主题

发表于 2013-11-19 17:28 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
  1. Option Explicit

  2. Function MinRot(ByVal sStr As String) As Long
  3.     Dim t#
  4.     t = Timer
  5.     '……
  6.     Dim i&, sTTT$, sYYY$, KKK&
  7.     sYYY = String(Len(sStr), "z")
  8.     For i = 1 To Len(sStr) - 1
  9.         sTTT = VBA.StrReverse(VBA.StrReverse(Left(sStr, i)) & VBA.StrReverse(Mid(sStr, i + 1)))
  10.         If sTTT < sYYY Then sYYY = sTTT: KKK = i
  11.     Next i
  12.     MinRot = KKK
  13.     t = Timer - t
  14.     Debug.Print "ID: " & "liuguansky"
  15.     Debug.Print "Answer is: " & MinRot & ":" & sYYY
  16.     Debug.Print "Time used: " & Format(t, "0.000s")
  17. End Function
复制代码
出这样的FUNCTION类的VBA,好难调试,而且测试数据源不多,不方便测试效率

评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2013-11-20 17:01 | 显示全部楼层
本帖最后由 oyzhjr 于 2013-11-22 17:10 编辑
  1.   Dim t#
  2.     t = Timer
  3.     Dim sStrLen As Long             '定义字符串长度
  4.     Dim js_a As Long            '定义计数变量
  5.     Dim charMin As String      '定义最小字母
  6.     Dim strTemp As String       '定义临时字符串
  7.     Dim strMin As String    '定义最小的字符串
  8.     Dim js_b As Integer         '定义计数变量,测试字母
  9.     sStrLen = Len(sStr)
  10.    
  11.     For js_b = 97 To 122            '查找最小的字母
  12.         If InStr(sStr, Chr(js_b)) > 0 Then
  13.             charMin = Chr(js_b)
  14.             Exit For
  15.         End If
  16.     Next
  17.    
  18.    
  19.     strMin = sStr
  20.     sStr = sStr & sStr
  21.     For js_a = 1 To sStrLen
  22.         If Mid(sStr, js_a, 1) = charMin Then
  23.             strTemp = Mid(sStr, js_a, sStrLen)
  24.             If strTemp < strMin Then
  25.                 strMin = strTemp
  26.                 MinRot = js_a
  27.             End If
  28.         End If
  29.     Next
  30.      If MinRot Then MinRot = MinRot - 1     '若为一个字母组成的串,值为0,否则实际运算后要减一才是次数
  31.    
  32.     t = Timer - t
  33.     Debug.Print "ID: " & "<oyzhjr>"
  34.     Debug.Print "Answer is: " & MinRot
  35.     Debug.Print "Time used: " & Format(t, "0.000s")
复制代码
======================
69000的长度,0.023s
ASUS N56 i5-3210CPU 8GRAM  不知道能过不。

函数解:=MODE(IF(TRANSPOSE(MID(A4&A4,ROW(INDIRECT("1:"&LEN(A4))),99))<MID(A4&A4,ROW(INDIRECT("1:"&LEN(A4))),99),"",ROW(INDIRECT("1:"&LEN(A4)))))-1   
138个字符,想不到更好的压缩办法了,等开题看高手的吧

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2013-11-21 17:10 | 显示全部楼层
原贴是在开放前上传的,无法删除,请楼主删除,根据题意,直接附上代码:

  1. Option Explicit

  2. '如果要在单元格中直接引用,传值的类型最好改为range

  3. '所以将函数原型进行了局部修改
  4. '原型:Function MinRot(ByVal sStr As String) As Long
  5. '改为:Function MinRot(ByVal rg As ) As Long


  6. Function MinRot(ByVal rg As Range) As Long
  7.     Dim t#
  8.     t = Timer
  9.     '……
  10.     Dim sStr As String
  11.    
  12.     sStr = Trim(rg.Value)
  13.    
  14.     If sStr <> "" Then MinRot = GetMin(sStr)  '我的函数
  15.     '----
  16.     t = Timer - t
  17.     Debug.Print "ID: " & "<Your ID>"
  18.     Debug.Print "Answer is: " & MinRot
  19.     Debug.Print "Time used: " & Format(t, "0.000s")
  20. End Function


  21. Function GetMin(strVal As String) As Long

  22.     Dim dicTemp As Object
  23.    
  24.     Dim strMinCounts As String '最小字符所在的位置集合
  25.     Dim lngLen As Long '字符串长度
  26.     Dim strMin As String '最小字符串
  27.     Dim lngMin As Long '最小字符串旋转次数
  28.    
  29.     Dim strTemp As String
  30.     Dim lngI As Long
  31.     Dim strT() As String
  32.    
  33.     Set dicTemp = CreateObject("Scripting.Dictionary")
  34.    
  35.    
  36.     lngLen = Len(strVal)
  37.    
  38.     '将每个字符串的位置记入 字典对象
  39.     For lngI = 1 To lngLen
  40.         strTemp = Mid(strVal, lngI, 1)
  41.         dicTemp(strTemp) = dicTemp(strTemp) & "," & lngI
  42.     Next
  43.    
  44.     '由于输入的字符串由小写英文字母‘a’~‘z’构成
  45.     '因此:
  46.    
  47.     '从a到z 读取所最小字符所在的位置串
  48.     For lngI = 97 To 122
  49.         strTemp = Chr(lngI)
  50.         If dicTemp.Exists(strTemp) Then
  51.             strMinCounts = Mid(dicTemp(strTemp), 2)
  52.             Exit For
  53.         End If
  54.     Next
  55.    
  56.     '取得位置数组
  57.     strT = Split(strMinCounts, ",")
  58.    
  59.     '如果最小字符只有一个,那就直接返回次数
  60.     If UBound(strT) = 0 Then
  61.        '旋转次数=所在的位置-1
  62.         GetMin = strT(0) - 1
  63.         Exit Function
  64.     End If
  65.    
  66.    
  67.     '如果最小字符出现1次以上
  68.     '将第一次出现的组合字符串先设置为最小字符串
  69.     strMin = Mid(strVal, strT(0)) & Mid(strVal, 1, strT(0) - 1)
  70.     lngMin = CLng(strT(0))
  71.    
  72.    
  73.     '从第二次出现的位置开始,与默认的最小字符串进行比较
  74.     For lngI = 1 To UBound(strT)
  75.         strTemp = Mid(strVal, strT(lngI)) & Mid(strVal, 1, strT(lngI) - 1)
  76.         '如果当前的字符串小于原有的最小字符串,重新设置
  77.         If strTemp < strMin Then
  78.             strMin = strTemp
  79.             lngMin = strT(lngI)
  80.         End If
  81.     Next
  82.    
  83.     '旋转次数=所在的位置-1
  84.      GetMin = lngMin - 1
  85. End Function


复制代码

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-11-23 15:40 | 显示全部楼层
本帖最后由 lee1892 于 2013-11-25 09:08 编辑

最近一直很忙,趁着有空,先把帖子结了。我这是VBA题,函数题由007写总结,呵呵~
测试结果见下图:


首先解释一下评分标准:
  • 图中:打勾表示通过;WA表示错误结果;KO表示超时;RTE表示运行错误(通常是内存溢出)。
  • 图中黑底白字的为字符数量10万个的运行结果,只有此处通过的才算。
  • 图中第一、二两项对应原题中评分标准的第一项。Random & Big Result 是为了保证获得的结果非常靠后,以避免随机字符测试中可能的结果很靠前而导致虽然是个很慢的算法依然能通过,同时由于设置了小字母的多次重复,而筛选可能的算法错误。
  • 对于10万随机字符分,如果在后续的测试中出现WA,则不会被记分,因为是算法出了问题,理论上是可能在随机字符测试中不能通过的。
  • 图中除第一、二两项的其余项对应原题中评分标准的第二项。
  • 由于我本以为是个较为简单的题目,没有预估到此题很少人能全通过,只设置了2个技术分,为鼓励大家的积极性,我建议对所有1000个字符获得通过的给予50到100的财富奖励,即算法正确能获得正确结果,版主考虑。


评分结果:
楼层论坛ID随机字符分特殊字符分优秀代码加分合计得分算法正确
财富奖励
备注
楼03yangyangzhifeng
1
楼05小花鹿
楼06香川群子1
楼07yuanhongly1
楼09JimmyBrian
楼10CheryBTL
楼11huahua2005
楼12doryan
楼14zm0115
楼15cleverzhzhf1
楼16gufengaoyue1
楼18jsxjd3
楼22hellohaha
楼23formatD
楼25liuguansky
楼26oyzhjr
楼27lsdongjh后续测试中的WA是
我添加超时判断强制退出造成的。


我准备的参考答案见13楼。曾邀请jsxjd也这么写一下的,貌似我没解释清楚,他的代码注释没有达到我想要的效果。

附件是我汇集的各楼的代码,包括我准备的,以及测试代码。其中Result表单为上图,Report表单则记录了所有测试的详细信息。
如希望在自己的机器上测试,则请尽量关闭已经打开的程序,重新开一个新的Excel进程,运行测试代码。
我发现题目中给出的速度参考代码很不稳定,我的机器上只有在新开进程的第一次运行中会得到接近0.5秒的速度,以后要改别的办法。

以上,如有疏漏请指出。
最后吐槽一下,论坛改显示效果要考虑向前兼容,现在的把[code]标签的功能给改了,复制是可以了,可[code=vb]这样的就一塌糊涂了,sigh~

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?免费注册

x

点评

50财富太多,算法正确的给予30财富奖励。  发表于 2013-11-27 16:01

TA的精华主题

TA的得分主题

发表于 2013-11-24 19:36 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
VBA不会
公式写了一个,太长,将就着看吧
  1. =MIN(IF(MIN(MMULT(CODE(MID(REPT(A2,100/LEN(A2))&REPT("}",99),MOD(COLUMN(A:CV)+ROW($1:$100)-2,100)+1,1)),10^-ROW($1:$100)*3-3))=MMULT(CODE(MID(REPT(A2,100/LEN(A2))&REPT("}",99),MOD(COLUMN(A:CV)+ROW($1:$100)-2,100)+1,1)),10^-ROW($1:$100)*3-3),ROW($1:$100)))-1
复制代码

评分

1

查看全部评分

您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-21 19:01 , Processed in 0.035938 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表